Skip to content

How to Configure CSP Nonce

Key idea:

CSP nonce — a random value, generated per request, included in the CSP header script-src 'nonce-XXX' and as the attribute <script nonce="XXX">. Lets a specific inline script execute without 'unsafe-inline', critical for XSS defence. Especially important for React SSR + legacy code.

Below: step-by-step, working examples, common pitfalls, FAQ.

Check your site →

Step-by-Step Setup

  1. Generate nonce per request: $nonce = base64_encode(random_bytes(16));
  2. Set CSP header: Content-Security-Policy: script-src 'self' 'nonce-<NONCE>' 'strict-dynamic'
  3. In HTML: <script nonce="<NONCE>">doStuff()</script>
  4. All other inline is blocked (as intended for XSS defence)
  5. For React/Next.js: via __webpack_nonce__ + middleware
  6. Verify: DevTools → Console → should be no "Refused to execute inline script"
  7. Enterno CSP Analyzer → grade = A

Working Examples

ScenarioConfig
PHP middleware$nonce = base64_encode(random_bytes(16)); header("Content-Security-Policy: script-src 'self' 'nonce-$nonce'");
Next.js middlewareconst nonce = Buffer.from(crypto.randomUUID()).toString('base64'); headers.set('Content-Security-Policy', `script-src 'self' 'nonce-${nonce}'`);
Inline script with nonce<script nonce="<?= $nonce ?>"> window.dataLayer = []; </script>
strict-dynamic (advanced)script-src 'nonce-XXX' 'strict-dynamic' # scripts loaded via nonce-script inherit trust
Report-Only for testingContent-Security-Policy-Report-Only: script-src 'self' 'nonce-XXX'; report-uri /csp-report

Common Pitfalls

  • Non-random nonce (timestamp, sequential) — attacker can predict
  • Reusing a nonce across requests — completely breaks security
  • Forgetting to add nonce to a legitimate inline script — blocked, sign-in form breaks
  • Google Analytics / GTM scripts don't expect nonce — use strict-dynamic or hash
  • CSP via HTML meta instead of HTTP header — ineffective for first-page XSS

TL;DR

To configure a Content Security Policy (CSP) with a nonce and remove 'unsafe-inline', generate a unique nonce for each request, insert it into your HTML, and apply it to your script tags. This approach enhances security by preventing the execution of unauthorized inline scripts while still allowing specific scripts to run.

Understanding Content Security Policy (CSP) and Nonce Usage

Content Security Policy (CSP) is a security feature designed to mitigate various types of attacks such as Cross-Site Scripting (XSS) and data injection attacks. By implementing CSP, web developers can specify which sources of content are trusted and which are not. A nonce (number used once) is a critical component that allows you to enable inline scripts without resorting to the less secure 'unsafe-inline' directive.

The primary goal of using a nonce is to enhance security while maintaining functionality. When a nonce is included in the CSP header, it must be added to the script tags in your HTML. This ensures that only scripts with the correct nonce value will be executed, effectively blocking any unauthorized inline scripts.

To set up a nonce-based CSP, follow these steps:

  1. Generate a unique nonce for each HTTP response.
  2. Add the nonce to your CSP header.
  3. Include the same nonce in your inline script tags.

Here’s a practical example of how to implement this:

const nonce = generateNonce(); // Function to generate a unique nonce

In your HTTP response header, set the CSP:

Content-Security-Policy: script-src 'self' 'nonce-{nonce}'

And in your HTML:

<script nonce="{nonce}">console.log('Secure Script');</script>

Replace {nonce} with the actual nonce generated for that request. This approach ensures that only scripts with the correct nonce are executed, effectively removing the need for 'unsafe-inline' and significantly enhancing your website’s security posture.

In the context of EU regulations, particularly the GDPR, ensuring robust security measures like CSP can help in compliance with data protection standards and prevent unauthorized access to user data.

Learn more

Frequently Asked Questions

Nonce vs hash — which?

Nonce — for dynamic HTML (per request). Hash — for static inline script (unchanged). In practice nonce + strict-dynamic covers 95% of cases.

What is strict-dynamic?

CSP3 directive: any script loaded via nonce/hash-script automatically inherits trust. Simplifies GTM/Analytics integration.

Does CSP work in IE?

IE 11 supports CSP 1 (basic). Nonce arrived in CSP 2 — no IE. Acceptable in 2026.

How do I check my CSP?

<a href="/en/csp">Enterno CSP Analyzer</a> → enter URL → grade + directive breakdown.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.