Content-Security-Policy: script-src 'nonce-4AEemGb0xJptoIGFP3Nd'; object-src 'none'; base-uri 'none'
<script nonce="4AEemGb0xJptoIGFP3Nd">initApp();</script>
Content-Security-Policy: script-src 'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8='
Both let your own scripts run without 'unsafe-inline'. An injected script has neither the nonce nor the right hash, so the browser blocks it.
Nonce-based: the server makes a new random value (a nonce, a number used once) for every response. It puts the value in the CSP header and in the nonce attribute of each of your <script> tags. An attacker can't guess the next value.
- It suits pages rendered per request, such as server-rendered apps. In Next.js you can set it in middleware.
- The page must not be cached and served with the same nonce, because a fixed nonce is easy to copy.
Hash-based: the policy lists the SHA-256 (or SHA-384 or SHA-512) hash of each inline script's exact text. The browser hashes each inline script and runs only the ones that match.
- It suits static pages on a CDN, where you can't make a new nonce per request.
- Any change to the script, even one space, changes the hash. So you must create the policy in your build step.
Both are often combined with 'strict-dynamic'. Then the scripts you trust can load more scripts, and you don't have to list every file.
- Both allow your own scripts while blocking injected ones, with no need for
'unsafe-inline'. - A nonce is a new random value for every response, placed in the header and on each script tag.
- Nonces fit server-rendered pages and break if a cached page reuses the same nonce.
- Hashes list the exact script text, so they fit static pages built ahead of time.
- Any change to an inline script changes its hash, so the build step must create the policy.