Using Hashes in CSP for Inline Scripts
Allow specific inline scripts and styles in CSP using cryptographic hashes. Learn how to compute SHA-256/SHA-384/SHA-512 hashes and when to prefer hashes over nonces.
Detailed Explanation
Hash-Based CSP
Hash-based CSP lets you allow specific inline scripts or styles by including a cryptographic hash of their content in the policy. The browser computes the hash of each inline block and compares it against the hashes in the CSP header.
How It Works
Write your inline script:
<script>alert('Hello');</script>Compute the SHA-256 hash of the script content (
alert('Hello');):echo -n "alert('Hello');" | openssl dgst -sha256 -binary | openssl base64 # Output: qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=Add the hash to your CSP header:
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='
Supported Hash Algorithms
CSP supports three hash algorithms:
- SHA-256 —
'sha256-...'(most commonly used) - SHA-384 —
'sha384-...' - SHA-512 —
'sha512-...'
SHA-256 is sufficient for CSP purposes. Using stronger hashes adds no practical security benefit for this use case.
Hash Sensitivity
The hash is computed over the exact content between the script tags. This means:
- Whitespace changes (even a single trailing newline) invalidate the hash
- Minification changes the hash
- Any modification, no matter how small, requires a new hash
<!-- These have DIFFERENT hashes -->
<script>alert('Hello');</script>
<script>alert('Hello'); </script> <!-- trailing space -->
<script>
alert('Hello');
</script> <!-- newlines -->
When to Use Hashes vs Nonces
Use hashes when:
- The inline script content is static and does not change between requests
- You are serving pages from a static site generator
- The HTML is cached by a CDN (nonces become stale with caching)
- You have a small number of known inline scripts
Use nonces when:
- Inline script content is dynamic (e.g., server-rendered data)
- You have many inline scripts that change frequently
- Your framework supports nonce injection (Next.js, Express, etc.)
- You want to use
'strict-dynamic'(which works with nonces but not hashes in older browsers)
Browser Hash Reporting
When a script is blocked, modern browsers report the expected hash in the console:
Refused to execute inline script because the script hash is not found in 'script-src'.
Either the 'unsafe-inline' keyword, a hash ('sha256-abc...'), or a nonce is required.
This makes it easy to extract the correct hash and add it to your policy.
Use Case
Hash-based CSP is ideal for static sites, documentation sites, and any page served from a CDN where nonce injection is not possible. A static blog with a small analytics snippet can hash it and include the hash in the CSP header. Jekyll, Hugo, and Astro sites that deploy to CDNs benefit from hashes since there is no server-side rendering to generate nonces.