CSP Generator

Build a Content-Security-Policy directive by directive, with strict and starter presets, nonce and hash support, live syntax validation and ready-to-paste server configuration.

Runs locally

Everything happens in your browser. What you paste or drop here is never uploaded, logged or stored.

Use the tool

A starting point, not an answer. Adjust the directives below.
Space separated. Added to the fetch directives that need them.

What a Content Security Policy actually does

A Content Security Policy is a response header that tells the browser which sources a page is allowed to load and execute code from. It does not stop an injection happening. What it does is decide what an injection is able to do once it has happened - and that is the difference between a defaced paragraph and an attacker running script with the full authority of your origin.

This tool builds that header directive by directive and explains the risk attached to each value, then produces configuration for the server you actually run. It also works the other way round: paste a policy you already have and it will tell you what is wrong with it.

Everything here runs in your browser

The policy you build or paste is never sent anywhere. That matters more than it might sound: a production CSP names your internal CDNs, your analytics vendors, your payment providers and sometimes staging hostnames that were never meant to be public. It is a map of your infrastructure, and it does not belong in someone else's server log.

The four directives that have no fallback

Most fetch directives fall back to default-src when absent, so setting default-src 'self' covers images, fonts, styles, connections and the rest. Four important directives do not participate in that fallback, and leaving them out means no restriction at all rather than an inherited one. This is the single most common way a policy does less than its author believes.

  • base-uri - controls what <base href> may be set to. Without it, one injected <base> tag silently repoints every relative script URL on the page at an attacker's host. No script tag needs to be injected at all; the ones you wrote do the work.
  • frame-ancestors - controls who may frame your page. This is the modern replacement for X-Frame-Options, and where both are present it takes precedence. Without it, anyone can frame you, which is what clickjacking requires.
  • form-action - controls where forms may submit. Without it, injected markup can retarget your login form to another origin, along with whatever it carries.
  • object-src - in practice always set this to 'none'. Legacy plugin content can execute script in ways script-src does not govern, and essentially no modern site needs it.

Why 'unsafe-inline' undoes most of the policy

'unsafe-inline' in script-src permits inline script - which is exactly what an injected <script> tag is. A policy with it still restricts which external hosts may serve scripts, but it no longer stops the most common form of cross-site scripting, which is the reason most sites deploy CSP in the first place.

The fix is a nonce: a fresh random value generated per response, placed on the <script> tags you control and named in the policy. There is a detail here worth knowing, because it saves an argument during rollout: when a nonce or hash is present, browsers from CSP Level 2 onward ignore 'unsafe-inline' entirely. So you can leave it in the policy as a fallback for very old browsers without weakening it for modern ones. This tool reports that case as informational rather than as a finding.

Use CSP Nonce and Hash Generator to produce nonces and hashes correctly, and check a live site with CSP Checker.

Roll out in report-only mode first

Enforcing a policy you have not measured will break a working site, usually in a way that only shows up for a subset of visitors. Deploy it as Content-Security-Policy-Report-Only first. The browser then evaluates the policy, reports what it would have blocked, and blocks nothing.

  1. Build the policy here and deploy it as report-only with a reporting endpoint.
  2. Leave it long enough to cover real traffic - a week catches weekly jobs and unusual browsers.
  3. Feed the reports into CSP Report Analyzer, which separates genuine blocks from browser-extension noise.
  4. Adjust until the only remaining reports are things you actually want blocked.
  5. Move the same policy to the enforcing Content-Security-Policy header.

Keep report-uri alongside report-to during this. report-uri is formally deprecated, but browser support for report-to is still incomplete and you will lose reports without it.

A note on the meta tag

A policy can be delivered in a <meta http-equiv> tag, but several directives are ignored there - frame-ancestors, report-uri and sandbox among them - and report-only mode does not work by meta tag at all. Use a response header wherever you can. This tool marks the meta output with those limitations rather than pretending they do not exist.

Frequently asked questions

Will adding a CSP break my site?

A strict one, deployed straight to enforcing mode, very likely will. That is why report-only exists and why this tool defaults to it. Deployed the way described above, the risk is small, because you will have seen everything the policy would block before it blocks anything.

Is 'strict-dynamic' better than listing hosts?

Usually, yes, for an application that loads script dynamically. It discards host allow-lists and trusts only script loaded by already-trusted script, so you stop maintaining a list of CDNs. It requires a nonce or hash to establish that initial trust - with neither, nothing loads at all, and this tool reports that combination as a high-severity finding because the symptom is a blank page.

Do I still need X-Frame-Options?

Only for very old browsers. frame-ancestors supersedes it and takes precedence where both are present. Sending both is harmless and is still common practice.

Why does my policy get a finding for having no report-uri?

Because without reporting you cannot tell whether the policy is blocking something legitimate. It is a low-severity finding rather than a high one - the policy still works - but it matters most during rollout, which is exactly when it tends to be left out.

Is my policy stored or sent anywhere?

No. Everything on this page runs in your browser. There is no request to a server carrying your policy, and nothing is written to storage.

References

What this tool can and cannot tell you. It reports what is present in the input you provide. It cannot see anything you did not give it, and a clean result means nothing was found in that input - not that the wider system is secure.

Security guidance here follows current published sources - OWASP, MDN, the relevant RFCs, NIST, CISA, FIRST and MITRE - which are linked beside the specific claims they support.

Rate this tool

Was this tool useful? Your feedback helps us improve it.

No ratings yet — be the first to rate this tool.
Your rating (required)
0 / 2000

Please do not include passwords, payment details or other sensitive information.

Your feedback is sent privately to the A2Z.Tools team and will not be posted publicly.