Skip to content
script-src.com
script-src.com
EN / FR

Nonces

How CSP script-src nonces work, how to generate them safely, and the mistakes that silently disable them.

A nonce allowlists a single inline script by tagging it with a random value that also appears in the header. Use nonces when your server renders pages dynamically and can emit a fresh value on every response.

How it works

Put the same random value in the script-src directive and on the script tag:

Content-Security-Policy: script-src 'nonce-2726c7f26c'
<script nonce="2726c7f26c">
  console.log('this inline script runs');
</script>

The browser executes the inline script only when the tag's nonce attribute matches the value in the header. An attacker who injects a <script> cannot guess the current nonce, so the injected script is blocked.

Rules that make a nonce safe

A nonce only provides protection if all of these hold:

  1. Fresh on every response. Generate a new value per HTTP response. A nonce that is reused across responses, or hard-coded in your template, gives an attacker a value they can copy.
  2. Unpredictable. Use a cryptographically secure random source with at least 128 bits of entropy, then base64-encode it. Do not derive it from the time, a counter, or the session ID.
  3. Server-generated. The value must come from the server that sets the header. You cannot add a nonce from client-side JavaScript, because the header is already parsed by then.

Generate it from a cryptographically secure random source on the server, for example 16 bytes from crypto.randomBytes base64-encoded, on every response.

unsafe-inline is ignored when a nonce is present

Browsers that support nonces ignore 'unsafe-inline' whenever a nonce or hash is present in the same directive. This lets you keep 'unsafe-inline' as a fallback for very old browsers without weakening modern ones:

script-src 'nonce-2726c7f26c' 'unsafe-inline'

Modern browsers honor the nonce and ignore 'unsafe-inline'. Ancient browsers that do not understand nonces fall back to 'unsafe-inline'.

Nonces and dynamically loaded scripts

A nonce applies to the exact tag it is placed on. If that script then injects more <script> elements, those children do not inherit the nonce and will be blocked. To let a trusted script load its own dependencies, combine the nonce with strict-dynamic.

Common mistakes

  • Rendering the nonce into a cached HTML fragment, so every visitor gets the same value.
  • Forgetting the nonce attribute on the tag while it is in the header, or the reverse.
  • Adding a nonce to an external script via src. That works, but the nonce is only needed when the host is not already allowlisted.