Developer Tools

CSP Nonce vs Hash for Static Websites

Choosing between a CSP nonce and a CSP hash depends on how your website is served. For static websites, hashes can be easier to maintain because they do not require a new value on every response.

A Content Security Policy (CSP) helps control which scripts and other resources a browser is allowed to load or execute. When a website needs inline scripts, two common CSP mechanisms are nonces and hashes.

Both can be used to allow specific inline code while keeping a stricter policy than unsafe-inline. However, they work differently and are suited to different website architectures.

For a static website, understanding the difference is particularly important because the way your HTML and HTTP headers are generated affects which approach is easier to maintain.

What Is a CSP Nonce?

A CSP nonce is a random value generated for a specific HTTP response. The same nonce is placed in the CSP header and on the trusted inline script.

For example:

Content-Security-Policy: script-src 'self' 'nonce-abc123';

The corresponding HTML would contain:

<script nonce="abc123">
  console.log("Trusted script");
</script>

The browser executes the script because its nonce matches the value declared by the CSP.

A nonce should be unpredictable and should not be reused as a permanent value. For dynamically generated pages, a new nonce is normally generated for each response.

What Is a CSP Hash?

A CSP hash works differently. Instead of generating a random value for each response, the policy contains a cryptographic hash calculated from the exact inline script content.

For example:

Content-Security-Policy: script-src 'self' 'sha256-...';

The browser calculates the hash of the inline script and compares it with the hash declared in the CSP.

If the content matches exactly, the browser allows the script to execute.

This makes hashes particularly useful when the inline code is static and predictable.

CSP Nonce vs Hash

Feature CSP Nonce CSP Hash
Value Random token Cryptographic hash
Usually generated Per response When the content changes
Requires dynamic response generation Usually No
Good for dynamic pages Yes Sometimes
Good for static HTML Can be inconvenient Often practical
Sensitive to script changes No, if nonce is regenerated Yes
Reusable policy Difficult with changing nonces Easier for unchanged content

The important difference is that a nonce is tied to the response, while a hash is tied to the exact content being allowed.

When Should You Use a CSP Nonce?

A nonce is useful when your website generates HTML dynamically and the inline scripts can change between requests.

For example, a server-rendered application might generate:

<script nonce="random-value">
  // Dynamic code
</script>

The server can generate the nonce and place the same value in the HTTP response's CSP header.

This approach works well when the application already has server-side logic capable of generating a fresh nonce.

The nonce must remain unpredictable. A fixed nonce such as nonce-123456 should not be treated as a secure implementation.

When Should You Use a CSP Hash?

A hash can be convenient when the HTML and inline scripts are static.

Suppose your page contains:

<script>
  console.log("Hello");
</script>

A SHA-256 hash can be calculated from the exact script content and added to the CSP policy.

The browser then allows that specific script because its content matches the declared hash.

This approach can work particularly well for static websites hosted through CDNs or static hosting platforms because the server does not need to generate a new nonce for every response.

Why Hashes Can Be Practical for Static Websites

Static websites usually serve the same HTML to many visitors.

If an inline script does not change, its hash does not need to change either.

This can make a hash-based CSP easier to deploy because the policy can remain fixed:

Content-Security-Policy: script-src 'self' 'sha256-...';

There is no need to generate a new nonce for every visitor.

However, this convenience comes with an important requirement: the hash must correspond exactly to the code being executed.

What Happens If You Change the Script?

A CSP hash is calculated from the exact content of the inline script.

Even a small change can produce a different hash.

For example:

<script>
  console.log("Hello");
</script>

and:

<script>
  console.log("Hello!");
</script>

do not have the same hash.

If you change the inline script but forget to update the CSP hash, the browser can block the script.

For a static website, this means that changing inline JavaScript should be treated as part of the CSP maintenance process.

What About External JavaScript?

External scripts are normally controlled using the script-src directive and trusted origins.

For example:

Content-Security-Policy: script-src 'self' https://example.com;

This allows scripts from the site's own origin and the specified external origin.

A hash or nonce is primarily useful for authorizing specific inline scripts. It does not automatically make every external resource safe.

You should therefore keep the list of trusted origins as narrow as practical.

Common CSP Mistakes

Using unsafe-inline

A policy such as:

Content-Security-Policy: script-src 'self' 'unsafe-inline';

allows inline scripts and significantly reduces the protection provided by a strict script policy.

If possible, use nonces or hashes for trusted inline code instead.

Using Broad Wildcards

Avoid unnecessarily broad policies such as:

Content-Security-Policy: script-src *;

A restrictive allowlist is generally easier to reason about and reduces the number of origins that can provide executable resources.

Reusing a Nonce

A nonce should not simply be generated once and reused indefinitely.

For dynamically generated responses, the nonce should be unpredictable and associated with the response being served.

Forgetting to Update Hashes

If an inline script changes, its CSP hash must also be updated.

This is one of the main maintenance considerations of a hash-based CSP.

Treating CSP as the Only Security Control

CSP is a defense-in-depth security mechanism.

It does not replace input validation, output encoding, safe DOM manipulation, or proper sanitization.

A strong CSP can reduce the impact of certain cross-site scripting vulnerabilities, but the underlying application should still prevent unsafe content from reaching executable contexts.

How to Choose Between a Nonce and a Hash

The architecture of your website is the most important factor.

A nonce is generally appropriate when:

A hash can be practical when:

For a purely static website, hashes can therefore be easier to maintain than dynamically generated nonces.

For a dynamic application, a nonce may fit the architecture better.

Build and Check Your CSP

Creating a CSP manually can become difficult when a website uses several scripts, stylesheets, fonts, images, APIs, or third-party services.

You can use the NeroTool CSP Generator to build a Content Security Policy based on the resources your website needs.

When working on a static site, pay particular attention to inline scripts. If you choose a hash-based approach, make sure the hash corresponds exactly to the script content that will be delivered.

After implementing the policy, test the website carefully and check the browser console for blocked resources.

A CSP should be introduced without breaking legitimate functionality.

Final Takeaway

CSP nonces and hashes solve a similar problem but are designed for different implementation scenarios.

A nonce is a random value associated with a specific response and is commonly useful for dynamically generated pages.

A hash is calculated from the exact content of an inline script and can be particularly practical for static websites where the code does not change frequently.

The important part is not simply choosing one mechanism. Your CSP should match the way your website is built, keep trusted resources as limited as practical, and be maintained whenever your scripts or resource requirements change.

For a static website with stable inline scripts, a hash-based policy can be a straightforward option. For dynamically generated pages, a nonce may integrate more naturally with the server-side architecture.

Open CSP Generator

Frequently asked questions

What is the difference between a CSP nonce and a CSP hash?

A CSP nonce is a random value generated for a specific HTTP response and added to trusted script or style elements. A CSP hash is a cryptographic hash of the exact inline script or style content. Nonces are generally suited to dynamically generated pages, while hashes can be practical for static pages.

Should a static website use a CSP nonce or hash?

A hash-based CSP is often easier for a static website because the policy can remain fixed and does not require generating a new nonce for every response. The choice still depends on how the site's scripts and other resources are delivered.

Does changing an inline script invalidate its CSP hash?

Yes. A CSP hash is calculated from the exact script content. Changing the script, even slightly, changes the hash, so the CSP policy must be updated with the new value.

Is a CSP nonce enough to prevent XSS?

No. A Content Security Policy is a defense-in-depth security control, not a replacement for input validation, output encoding and proper sanitization. A strong CSP can reduce the impact of some XSS vulnerabilities when it is correctly implemented.

AdvertisementAd space — reserved, no network calls until AdSense is enabled