CSP Validator
CSP
CSP Validator
Paste a Content-Security-Policy header and get a security grade, the exact weaknesses ranked by severity, and a paste-ready fix for each — plus a strict-policy generator and formatter. Everything runs in your browser.
EvaluateGenerateFormat
Paste a Content-Security-Policy header value
Evaluate policy Try a sample
What a Content Security Policy actually does
A Content Security Policy (CSP) is a browser security standard — published by the W3C, not the IETF, so it has no RFC number — that lets you declare which sources of scripts, styles, images, and other resources a page is allowed to load. The browser blocks anything outside that allowlist. Its primary job is to blunt cross-site scripting (XSS): even if an attacker injects a `<script>`, a strong CSP stops it from executing. It also helps against clickjacking (via `frame-ancestors`) and mixed content.
The evaluator above parses a policy, grades it against the W3C CSP Level 3 specification and OWASP hardening guidance, and — unlike a raw pass/fail checker — hands you the corrected directive to paste back. It runs entirely client-side; nothing you paste leaves your browser.
CSP hardens the browser half of your domain's security posture. The mail half is a separate stack: DMARC to stop spoofing of your domain, MTA-STS to force TLS on inbound mail, and Domain Health Check to scan all of it at once.
Where you set a CSP
Two delivery methods. The HTTP response header is the real one:
Content-Security-Policy: default-src 'self'; script-src 'self'You can also use a `<meta http-equiv="Content-Security-Policy">` tag, but it is strictly weaker: `frame-ancestors`, `report-uri`/`report-to`, and `sandbox` are ignored in a `<meta>` policy and only work as a header. In practice you set the header at your web server or CDN (nginx, Apache, Cloudflare, etc.), which is where most real-world tuning happens.
The directives that matter most
| Directive | Controls | | --------------- | ------------------------------------------------------------ | | default-src | Fallback for every fetch directive you don't set explicitly. | | script-src | Where JavaScript may load and execute. The highest-risk one. | | style-src | Where CSS may load from. | | object-src | Plugins (<object>/<embed>). Set to 'none'. | | base-uri | Restricts <base> so injected tags can't rewrite URLs. | | frame-ancestors | Who may embed your page in an iframe (clickjacking defense). | | report-to | Where the browser sends violation reports. |
Why `'unsafe-inline'` and `'unsafe-eval'` are dangerous
`'unsafe-inline'` in `script-src` re-allows inline `<script>` blocks and event handlers — the exact thing CSP exists to stop — so it defeats most of your XSS protection. `'unsafe-eval'` re-enables `eval()` and the `Function()` constructor. The modern answer is a nonce (a fresh random value per response, echoed on each inline script) or a hash of the script's contents, usually paired with `'strict-dynamic'` so trusted scripts can load their own dependencies. When a nonce or hash is present, browsers automatically ignore `'unsafe-inline'`.
Rolling out safely with Report-Only
Never ship a strict CSP straight to enforcement — you will break something. Deploy it first in report-only mode, which reports violations without blocking:
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpointWatch what it would have blocked, fix the false positives, then switch the header to `Content-Security-Policy` to enforce.
Catching violations in production
The modern way to collect violations is the `report-to` directive plus a `Reporting-Endpoints` response header (whose syntax follows RFC 9651, HTTP Structured Field Values, which obsoletes RFC 8941). Ship `report-uri` alongside it:
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"
Content-Security-Policy: default-src 'self'; report-uri https://example.com/csp-reports; report-to csp-endpointUse both. `report-uri` is deprecated in favour of `report-to`, and Chromium-based browsers ignore it when both are present — but Firefox and Safari do not implement the Reporting API for CSP, so `report-uri` is the only directive they honour. Ship `report-to` alone and you receive nothing from those browsers. Reports arrive as JSON POSTs; collecting and de-noising them at scale is what a hosted CSP monitor does.
Fixing a CSP console error
When the browser console shows "Refused to load … because it violates the following Content Security Policy directive", don't disable CSP — read the directive it names (e.g. `img-src`), confirm the blocked source is one you trust, and add that source to that directive. Then re-test. Disabling CSP to make an error go away removes the protection entirely; the fix is almost always a one-line directive change.
Read the complete CSP guide to learn more.
Frequently asked questions
Do I need a Content Security Policy?
If your site runs any JavaScript or accepts user input, yes. A CSP is a second layer of defense that makes cross-site scripting far harder to exploit even when a vulnerability slips through. It is a defense-in-depth control, not a fix for the underlying bug.
What is a Content-Security-Policy example?
A strict starting point: default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; upgrade-insecure-requests. The generator on this page builds one for you.
How do I fix a CSP console error?
Read the directive named in the error (for example img-src), confirm the blocked source is one you trust, and add it to that directive. Do not disable CSP to silence the error — that removes the protection. The fix is almost always a one-line directive change.
Is 'unsafe-inline' safe to use?
No. 'unsafe-inline' re-allows inline scripts, which is the main thing CSP exists to block, so it defeats most of your XSS protection. Use a per-response nonce or a hash instead; browsers ignore 'unsafe-inline' when a nonce or hash is present.
report-to vs report-uri — which should I use?
Use both. report-to with a Reporting-Endpoints header is the modern method, and Chromium-based browsers ignore report-uri when both are present. But Firefox and Safari do not implement the Reporting API for CSP, so report-uri is the only reporting directive they honour — ship report-to alone and you receive no violations from those browsers.
Should I set CSP as a header or a meta tag?
Prefer the HTTP response header. A <meta> CSP works for basic cases but ignores frame-ancestors, report-to/report-uri, and sandbox — those only take effect when delivered as a real header.
Related Tools
MTA-STS MTA-STS Checker Enforce TLS on inbound mail — transport-layer hardening. DNS Domain Health Check Score your domain across DMARC, SPF, DKIM, MTA-STS and more. DMARC DMARC Record Checker Validate the email-authentication half of your posture.
Get the full picture with DMARCguard
Continuous monitoring, aggregate report parsing, and actionable insights for all your email authentication protocols.
