\n \n\n2. Compute the SHA-256 hash of the script content (alert('Hello');):\n bash\n echo -n \"alert('Hello');\" | openssl dgst -sha256 -binary | openssl ba"}},{"@type":"Question","name":"When is this useful?","acceptedAnswer":{"@type":"Answer","text":"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."}}]}

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.

Common Policies

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

  1. Write your inline script:

    <script>alert('Hello');</script>
    
  2. 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=
    
  3. 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.

Try It — CSP Header Generator

Open full tool