CSP Header Generator
Build Content-Security-Policy headers with directives, hashes, and nonces. Strict-mode templates, report-only fallback, plus Express and Nginx snippets. Runs in your browser.
- Runs in your browser
- Your data never leaves your browser
- Free · No Sign-Up
Scan with WeChat to share this tool
Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.
Strict CSP starter
The Strict preset follows the nonce-based strict CSP described on web.dev. The HTTP header tab shows:
Content-Security-Policy: default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
'nonce-{RANDOM}' is a placeholder, not a value. Your server must replace it with a new random value of at least 128 bits on every response, and write the same value into nonce=”…” on each <script> it renders. The tool shows a warning while the placeholder is in the policy. Do not paste one fixed nonce into a static config: anyone who sees it once can reuse it in an injected script.
The placeholder replaces the ‘self’ that earlier versions of this preset used. With ‘strict-dynamic’, CSP Level 3 blocks every script that the HTML parser inserts unless it has a matching nonce or hash, and it stops checking ‘self’ and host sources (CSP3 §8.2). So script-src ‘self’ ‘strict-dynamic’ on its own runs no script at all in current Chrome, Firefox and Safari, and the tool now warns about that combination. If your site is a static build that cannot set a nonce, remove the placeholder and add a hash for each inline script with the hash calculator, or start from the Moderate preset.
The Express (helmet) tab does the per-response part for you: it adds a middleware that stores crypto.randomBytes(16).toString(‘base64’) in res.locals.cspNonce and passes script-src a function, which is the pattern in the helmet README. Your templates still have to print that value on each script tag. The Nginx tab keeps the placeholder and adds a comment, because Nginx cannot put the same nonce into the HTML your application renders.
Common pitfalls
’none’only works alone. If you list another source next to it,‘none’has no effect and the other sources are allowed.- Some directives are HTTP only. CSP3 §3.3 ignores
frame-ancestors,report-uriandsandboxin<meta>, and Report-Only mode does not exist there. The tool leaves these out of the<meta>tab and warns you. ‘strict-dynamic’needs a nonce or hash. Without one it blocks every script on the page; the tool flags this.- Hashes and nonces void
‘unsafe-inline’. Modern browsers fall back to the safer of the two when both are present. - Always set
default-src. Missing fetch directives fall back todefault-src; without it the browser applies no fallback for new directives added later. - Custom hosts cannot contain semicolons. A semicolon would terminate the policy and corrupt every directive after it.
Hashes vs. nonces
Use hashes for static inline content that ships with the page — analytics snippets, critical CSS, server-rendered helpers. Hashes work for static HTML and edge-cached responses because they do not need any per-request value.
Use nonces for dynamic content rendered per request. The server emits a Content-Security-Policy header containing ‘nonce-XYZ’ and stamps the same value on every <script nonce=“XYZ”> it renders. Pair nonces with ‘strict-dynamic’ so descendant scripts inherit trust without you maintaining a host allow-list.
Deployment cheat sheet
- Nginx: copy the Nginx tab into your
serverblock and reload — thealwaysflag forces the header on error responses too. - Apache: use
Header always set Content-Security-Policy ”…”in.htaccessorhttpd.conf. - Express / Node: paste the helmet snippet, and remember to disable
useDefaultsso your policy is not silently merged with helmet defaults. - Cloudflare Pages / Vercel / Netlify: paste the HTTP header form into your platform’s headers config (
_headers,vercel.json,netlify.toml).
FAQ
What is a Content Security Policy?
A CSP is an HTTP response header that tells browsers which sources of scripts, styles, images, fonts, frames, and other content are trusted. Together with output encoding, it is the strongest browser-side defense against cross-site scripting, clickjacking, and data injection attacks.
Should I deploy Enforce or Report-Only first?
Always roll out with `Content-Security-Policy-Report-Only` plus a `report-uri` (or `report-to`) endpoint. Watch real traffic for one to two weeks, fix legitimate violations in your code, then switch to enforced `Content-Security-Policy`.
Do I need 'unsafe-inline' for inline scripts and styles?
Avoid it whenever you can. Modern CSP supports per-script hashes (`'sha256-...'`, `'sha384-...'`, `'sha512-...'`) and per-request nonces (`'nonce-...'`). Use the inline-content hash calculator on this page to add a hash for a specific snippet.
What does 'strict-dynamic' do?
'strict-dynamic' lets a trusted nonced or hashed script load further scripts at runtime without listing every CDN. It is the recommended pattern for modern apps because it overrides host-based allow-lists for descendant scripts and stops trivial bypasses.
Where do I deploy the generated header?
Send `Content-Security-Policy` from your origin server (Nginx `add_header`, Apache `Header set`, Cloudflare Transform Rules, Vercel `headers`, etc.). The HTML `<meta http-equiv>` form is a fallback for static hosts; CSP Level 3 ignores `frame-ancestors`, `report-uri` and `sandbox` in `<meta>`, so the tool leaves them out of that tab. `report-to` still works there, but its endpoint is defined in a `Reporting-Endpoints` header.