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.
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-endpoint Watch 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-endpoint Use 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.
Get the full picture with DMARCguard
Continuous monitoring, aggregate report parsing, and actionable insights for all your email authentication protocols.
Start Free