CSP Generator
Build a Content-Security-Policy header, with warnings for the settings that quietly switch protection off. Runs in your browser.
Start from
Directives
Mode
Format
Output
How to Generate a Content Security Policy
- Start from a preset, or build from scratch.
- Set each directive's allowed sources.
- Add the third-party origins your site actually uses.
- Read the warnings about settings that weaken the policy.
- Copy the header, deploy it report-only first, then enforce.
Nothing is uploaded — the policy is built in your browser.
Deploy it report-only first
This is the single most useful thing to know about CSP, and the step most people skip.
Content-Security-Policy-Report-Only enforces nothing. The browser evaluates the
policy, reports what it would have blocked, and lets it load anyway. Your site cannot
break.
Run that against real traffic for a week. You will find third parties nobody remembered: a marketing pixel, an embedded map, a font host, a chat widget added two years ago. Add the legitimate ones, then switch the header name to the enforcing version. Going straight to enforcement is how a policy takes down a checkout on a Friday.
Both headers can be sent at once — enforce a policy you trust while testing a stricter one report-only.
Source keywords
| Value | Means |
|---|---|
| 'self' | Same origin as the document — same scheme, host and port. The workhorse. |
| 'none' | Nothing at all. Correct for object-src on virtually every modern site. |
| 'unsafe-inline' | Permits inline scripts and styles. Removes most of the protection for script-src — prefer a nonce or hash. |
| 'unsafe-eval' | Permits eval and new Function. Some older frameworks and template engines need it; most current ones do not. |
| 'nonce-…' | Permits the specific inline scripts carrying this nonce. Must be regenerated per response — a static nonce is worthless. |
| 'sha256-…' | Permits an inline script whose content hashes to this. Good for a fixed snippet that never changes. |
| 'strict-dynamic' | Trusts scripts loaded by an already-trusted script, and makes host allowlists be ignored. The modern approach, paired with nonces. |
| https: | Any origin over HTTPS. Broad enough that it is barely a policy — it permits every host on the internet. |
| data: | data: URIs. Reasonable for img-src, dangerous for script-src, where it lets an attacker inline whatever they like. |
The directives that do not fall back
Most fetch directives inherit from default-src when you leave them out. Three
important ones do not, and a policy that sets only default-src leaves all three
wide open:
frame-ancestors— who may put your page in an iframe. This is the modern replacement forX-Frame-Options, and without it your site can be framed for clickjacking.form-action— where a form on your page may submit. Without it, an injected form can post your users' input to an attacker's server.base-uri— restricts the<base>element, which can otherwise repoint every relative URL on the page somewhere else.
All three are in the list above and set to 'self' by the presets, because the
omission is easy to make and costly.
Specifications
- Accepts
- No file needed
- Gives you
- csp-header.txt download · copy to clipboard
- Where it runs
- Your browser — the file is never uploaded
- Sign-up
- None
- Cost
- Free, with no usage limits
FAQ
What does a Content Security Policy do?
It tells the browser which sources a page is allowed to load scripts, styles, images and other resources from, and refuses everything else. Its main job is limiting the damage of cross-site scripting: even if an attacker manages to inject a script tag, a policy that does not permit that origin stops it running.
Should I start in report-only mode?
Almost always. Content-Security-Policy-Report-Only applies nothing and breaks nothing — it just reports what would have been blocked. Run it for a week on real traffic, read the reports, fix the legitimate sources, then switch to enforcing. Deploying an untested policy straight to enforcement is how sites break their own checkout.
Why is unsafe-inline flagged?
Because it removes most of the protection you came for. The main thing a CSP stops is injected inline script, and unsafe-inline permits exactly that. If inline scripts are unavoidable, a nonce or a hash allows the specific ones you control while still blocking anything injected.
What is the difference between default-src and the rest?
default-src is the fallback for any fetch directive you did not set. Setting default-src self and nothing else is a strong, simple starting policy. Note that some directives — frame-ancestors, form-action, base-uri — do not fall back to default-src, so they need setting explicitly.
Header or meta tag?
The HTTP header, whenever you can. A meta tag works but arrives after parsing has started, cannot use frame-ancestors, report-uri or sandbox, and cannot be report-only. Use the meta form only on static hosting where you cannot set headers.
Will this policy work as is?
It is a starting point you still have to test. No generator can know which third parties your site actually loads — analytics, fonts, embeds, payment widgets all need their origins listed. That is exactly what report-only mode is for.