CSP Header Generator
Developer Tools · Added
A Content-Security-Policy tells the browser what your page is allowed to load and run, which is what turns an injected script from a breach into a console error. This builds one directive by directive, checks it for the settings that make a policy decorative rather than protective, and gives you the header in the form your server wants it.
Your policy
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; upgrade-insecure-requests- Directives
- 11
- Critical issues
- 0
- Warnings
- 0
Nothing that defeats the policy
- Note · Content-Security-Policy-Report-OnlyReport-only mode blocks nothing. It is the right way to start — deploy it, watch the reports for a week of real traffic, then switch the header name once they are quiet.
Setting the header
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; upgrade-insecure-requests" always;As a meta tag
A meta tag cannot be report-only — that mode exists only as a header.
Every warning above comes from reading the policy, not from testing it: this page never fetches your site and cannot know what your pages actually load. A policy that looks right here can still break something, which is what report-only mode is for — deploy it, watch real traffic for a week, then change the header name once the reports are quiet. Nothing you type is sent anywhere.
How to use the csp header generator
- 1Start from one of the three presets, or from an empty policy.
- 2Fill in the directives your site needs. The keyword buttons under each field add the quoted values correctly.
- 3Read the warnings — critical ones mean the policy does not do what it looks like it does.
- 4Copy the header, or the server snippet, and deploy it in report-only mode first.
Examples
A policy that looks strict and is not
- Input
- script-src 'self' 'unsafe-inline'
- Result
- Critical: 'unsafe-inline' allows exactly what cross-site scripting needs
The single most common way a CSP ends up protecting nothing.
A quoting mistake
- Input
- default-src self
- Result
- Critical: self must be written 'self' — unquoted, the browser reads it as a hostname
A directive a meta tag cannot carry
- Input
- frame-ancestors 'none'
- Result
- The meta tag is withheld, with the reason: browsers ignore frame-ancestors there. Send it as a header
About the csp header generator
What a CSP is actually defending
The threat model is straightforward: an attacker finds a way to get markup into your page — a comment field, a URL parameter reflected into HTML, a third-party widget — and uses it to run JavaScript in your users' sessions. Everything that session can do, the script can do.
A Content-Security-Policy makes the browser the enforcement point. The injection may still land in the HTML, but if the policy says scripts may only come from your own origin and carry a nonce the attacker cannot guess, the browser refuses to run it and reports the attempt. That is a much stronger position than trying to sanitise every input path perfectly, because it does not depend on getting every path right.
The directives people forget
Three directives do not fall back to default-src, so leaving them out leaves them unrestricted no matter how strict the rest of the policy is. frame-ancestors controls who may put your site in an iframe and is the modern replacement for X-Frame-Options; without it, clickjacking is available to anyone. base-uri limits what a base element may set, and an injected base element repoints every relative URL on the page, script sources included. form-action controls where your forms may submit, which is how an injected form exfiltrates a password manager's autofill.
object-src does fall back to default-src, but it is worth setting to 'none' explicitly. Plugins are gone from browsers, nothing legitimate needs it any more, and object and embed elements remain a route worth closing by name rather than by inheritance.
Why a policy usually gets weaker after deployment
The pattern is familiar: a strict policy goes out, something breaks, and the fastest fix is to add a source to the directive that blocked it. Do that a few times and the policy allows https: for scripts, which allows every CDN that hosts a copy of a library capable of running arbitrary code, which is most of them.
The way out is to treat each break as a question about the site rather than about the policy. A blocked inline handler usually means an event handler that belongs in a script file. A blocked CDN usually means a dependency nobody chose deliberately. The policy is a fairly accurate inventory of what a page loads, and the parts of it that feel unreasonable are often the parts of the page that are.
Frequently asked questions
Why is 'unsafe-inline' such a problem?
What does 'strict-dynamic' do?
Should I use the header or the meta tag?
What is report-only mode for?
Does this check my site?
Related tools
Robots.txt Generator
Developer Tools
Build a robots.txt with per-crawler rules, and get it checked for the usual mistakes.
Meta Tag Analyzer
Developer Tools
Audit a page's title, description and social tags from its HTML, with card previews.
Hash Generator
Developer Tools
Generate SHA-256, SHA-384, SHA-512 or SHA-1 digests of text or a file, and verify a checksum.
ASCII Table
Developer Tools
Searchable ASCII reference with decimal, hex, octal, binary and escapes.