CSP validator. Per-directive, with strict-CSP audit.
Paste your Content-Security-Policy header. We parse every directive, flag unsafe-inline / unsafe-eval / wildcards, surface missing protections, and recommend the modern strict-CSP nonce pattern from Google's CSP guide.
Paste a Content-Security-Policy header value. We parse every directive, audit unsafe-inline / unsafe-eval / wildcard usage, surface missing protections, and provide a per-directive verdict + overall security grade. Recommendations follow Google's strict-CSP guidance.
- —
Sources used
- W3C Content Security Policy Level 3 — canonical spec
- MDN CSP reference — directive behavior + browser support
- MDN Content-Security-Policy header — every directive documented
- Google CSP Evaluator — additional cross-check (research reference)
- OWASP Secure Headers — CSP — hardening recommendations
- web.dev Strict CSP guide — nonce + hash strategies
No data is sent to any external service. The validator parses your CSP entirely in the browser, runs every per-directive check (unsafe-inline, unsafe-eval, wildcards, missing critical directives) locally, and produces the audit grade in your tab. The source links above are reference documentation only.
Privacy: parsing happens in your browser. Nothing is sent or logged.
Strict CSP vs allowlist. Different trade-offs.
Allowlist CSP. List every domain that's allowed: script-src 'self' https://cdn.jsdelivr.net https://www.googletagmanager.com. Easy to start; hard to maintain. Every new third-party script (analytics tool, A/B tester, chat widget) needs a CSP update. Miss one, the page breaks. Ship a typo, the page breaks. The protection is real but the maintenance burden compounds. Most production sites still use this pattern because of legacy build pipelines.
Strict CSP. Google's recommended modern pattern. Use a per-page nonce on every inline script tag, plus 'strict-dynamic' to allow trusted scripts to load further trusted scripts. script-src 'self' 'nonce-r4nd0m' 'strict-dynamic'. No allowlist needed. Adding a new third-party widget = no CSP change required (the trusted inline script that loads it propagates trust). Maintenance burden: near zero. Implementation cost: every inline script tag needs the nonce attribute, which means the build pipeline / framework has to inject it.
When to pick which. New project, modern framework (Next.js, Remix, Astro, SvelteKit): strict CSP. Existing project with hundreds of inline scripts and no centralized rendering pipeline: allowlist CSP, then plan a migration to strict over a few quarters. Either is dramatically better than no CSP. Don't let perfect-strict-CSP block shipping a working allowlist; ship the allowlist, then iterate.
Four jobs this tool covers.
Job 1: Author + verify a new CSP. Before pushing a new CSP live, paste here. The directive-by-directive verdict catches the common mistakes — accidentally including 'unsafe-eval', missing the object-src 'none' hardening, forgetting base-uri. Fix before deploy, not after the report-only logs flood.
Job 2: Audit a vendor's CSP. Evaluating a SaaS or partner integration that requires you to load their CSP? Paste it here. Vendors that ship loose CSP (unsafe-inline, wildcards) signal lower security maturity and may bring XSS risk into your stack. The grade tells you how seriously they take security headers.
Job 3: Plan a strict-CSP migration. Your current CSP is a long allowlist. Run it through, see the warnings about 'unsafe-inline' in style-src or missing strict-dynamic. The recommendations form the migration backlog. Pair with our HTTP Headers Checker to confirm the full security-header stack alongside CSP.
Job 4: Investigate report-uri / report-to data. If you've collected CSP violation reports from production, the patterns tell you what your CSP is blocking. Paste your CSP here, then cross-reference the violation reports to identify whether the blocks are legitimate XSS attempts (the policy is working) or false positives that need a CSP relaxation.
Six questions users ask.
Why is unsafe-inline a problem?
unsafe-inline allows inline scripts (script tags with code inside, onclick handlers in HTML, javascript: URLs). The whole point of CSP is to block scripts that weren't part of your trusted code; unsafe-inline removes that protection. If an attacker injects a script tag into your HTML via XSS, the browser executes it because unsafe-inline allowed it. Modern best practice (Google's strict-CSP pattern): use nonces or hashes per script tag instead of allowing all inline. Slightly more work to author, dramatically more protection.
What's the difference between allowlist CSP and strict CSP?
Traditional allowlist CSP lists every domain that's allowed to load scripts (script-src self https://cdn.jsdelivr.net https://www.googletagmanager.com ...). Hard to maintain — every new third-party script needs a CSP update; one missed domain breaks pages. Strict CSP uses nonces (random per-page tokens added to script tags) plus 'strict-dynamic' (allow-listed scripts can load further scripts they trust) — no allowlist needed. Google's strict-CSP is the modern recommendation; works for most applications and is dramatically easier to maintain. allowlist is still in heavy use because of legacy tooling.
What directives should every CSP have?
Five at minimum. (1) default-src — fallback for any directive not explicitly set. Set to 'self' as the safe default. (2) script-src — controls JS loading. Most security-critical. Use nonces in modern apps. (3) style-src — controls CSS loading. (4) img-src — controls image loading; usually safe to be permissive (img-src self data: https:). (5) object-src — should be 'none' (blocks Flash/legacy plugins). (6) base-uri — should be 'self' or 'none' (prevents base-tag injection attacks). (7) frame-ancestors — clickjacking protection (replaces X-Frame-Options for modern browsers). The validator flags missing items from this list.
What's the deal with 'strict-dynamic'?
strict-dynamic in script-src tells the browser: 'trust scripts loaded by other trusted scripts.' Lets you skip the explicit allowlist for transitively-loaded scripts (a trusted script that loads jQuery, which loads a plugin). Combined with nonces, strict-dynamic enables maintainable CSP for complex apps — you nonce your initial scripts, and they can dynamically load whatever they need. The catch: strict-dynamic ignores allowlists when nonces are present. So you can't combine allowlist + strict-dynamic and expect both to work; the nonce-and-strict-dynamic combo wins.
Should I use Content-Security-Policy or Content-Security-Policy-Report-Only?
Report-Only first, then enforce. Content-Security-Policy-Report-Only logs violations but doesn't block — perfect for testing a new CSP without breaking the site. Set up a report-uri or report-to endpoint to receive violation reports, monitor for 1-2 weeks, fix any legitimate uses that the CSP would have blocked, then switch to enforcing Content-Security-Policy. Skipping the report-only phase risks breaking pages on launch when a missed third-party script gets blocked. Even mature sites should keep a small report-uri running in production for ongoing visibility.
Is the CSP I paste sent anywhere?
No. Parsing happens entirely in your browser. The page is static HTML; the only network request is the initial page load. Safe for CSPs from internal staging environments, security-sensitive production configs, or any policy you don't want to share with a third party.
Published .