Safeguard
Security Guides•

CSP nonce vs hash vs host allowlist: which should you use?

Pick a nonce for dynamic pages, a hash for static ones, and avoid long host allowlists. Learn strict-dynamic, report-only rollout and directives to add.

Safeguard Security Team
3 min read

Use a nonce for pages your server renders on each request, a hash for static pages, and avoid long host allowlists. MDN calls nonce and hash policies a strict CSP and recommends them over allowlists, which tend to permit more than intended. Start in report-only mode so you see breakage before users do.

The three approaches

Nonce. The server makes a random value for every response, puts it in script-src 'nonce-...' and sets the same value on each script tag you trust. The value must change on every response and be unpredictable. That means templating, not static files.

Hash. You compute a SHA-256, SHA-384 or SHA-512 hash of a script, Base64 encode it, and list it in the policy. External scripts also need an integrity attribute. Any edit to the script means recomputing and redeploying the hash, so this fits static pages.

Host allowlist. You list sites, such as 'self' or *.example.org. MDN warns these are hard to get right and often whitelist unsafe domains. It cites a case where adding one analytics provider meant adding 187 domains.

Which to choose

  • Server rendered, dynamic: best fit: Nonce
  • Static HTML: best fit: Hash
  • Many third party scripts: best fit: Nonce or hash plus strict-dynamic
  • Legacy with inline handlers: best fit: Refactor first, then nonce

What strict-dynamic does

A script with a valid nonce or hash may load more scripts without a nonce of their own, and trust passes down the chain. That helps when a trusted loader pulls in dependencies. MDN notes the trade: if trusted scripts build script elements from an XSS source, the policy will not block them.

Directives to include

MDN's strict policy examples add two lines that are easy to forget:

  • object-src 'none' blocks plugin content.
  • base-uri 'none' stops the base element from changing how relative URLs resolve.

Also consider frame-ancestors 'none' unless your site must be embedded. Avoid 'unsafe-inline'. MDN adds that browsers ignore it when a nonce or hash is present in the same directive.

A rollout plan

  1. Send Content-Security-Policy-Report-Only with your draft policy. MDN says both headers can be present, one enforcing and one reporting. Report-only cannot be delivered through a meta element.
  2. Set up reporting endpoints and collect violations.
  3. Replace inline handlers with addEventListener() and remove javascript: URLs and eval().
  4. Send the policy on all responses, not just the main document.
  5. Switch to enforcement once reports go quiet.

What a CSP is not

OWASP says a CSP should not be your primary defence against XSS, since mistakes are easy to make. Keep output encoding and safe DOM APIs in place. MDN also notes that upgrade-insecure-requests does not replace HSTS.

Quick check

Can I reuse the same nonce on every page load?

No. A reused nonce can be learned and abused. It must be new and unpredictable for each response.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.