How to Validate a Content Security Policy Before Deploying
Deploy as Content-Security-Policy-Report-Only first — violations appear in the browser console without blocking anything. Use the CSP Validator to check for unsafe directives and missing protections. Switch to enforcing only when violations stop.
A wrong CSP breaks your site silently — fonts stop loading, analytics disappear, iframes stop embedding. Validate before enforcing to catch every issue without affecting users.
Validate your CSP now →Step 1 — Deploy in report-only mode first
Never deploy a new CSP directly as enforcing. Use Content-Security-Policy-Report-Only — identical syntax, zero blocking:
# Nginx — report-only, nothing blocked add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'; object-src 'none';" always;
Violations appear in the browser console as warnings, not errors. Check DevTools → Console for a few days before switching to enforcing.
Step 2 — Validate the policy string
The CSP Validator checks your policy against the W3C CSP Level 3 spec and flags:
- Critical:
'unsafe-inline'in script-src, missingdefault-src, wildcard in script-src - Warnings: missing
frame-ancestors, missingbase-uri, HTTP sources - Info:
'unsafe-inline'in style-src, missingupgrade-insecure-requests
What to check manually
1. default-src is set
Without default-src, any resource type not explicitly listed is implicitly allowed. Always set a baseline:
default-src 'self'; # Good baseline — blocks all external by default
2. frame-ancestors is present
frame-ancestors is not covered by default-src — it must be explicit. It replaces X-Frame-Options:
frame-ancestors 'none'; # Block all framing frame-ancestors 'self'; # Allow same origin only
3. object-src 'none' is set
Without this, Flash and plugins are allowed. Always disable:
object-src 'none';
4. No wildcard in script-src
# Dangerous — allows scripts from anywhere script-src *; # Correct — explicit domains only script-src 'self' https://www.googletagmanager.com;
Step 3 — Switch to enforcing
When the browser console shows no more CSP violations for 2-3 days across different pages, switch from report-only to enforcing:
# Before add_header Content-Security-Policy-Report-Only "..." always; # After add_header Content-Security-Policy "..." always;
Common CSP that breaks things
| What breaks | What to add |
|---|---|
| Google Fonts | style-src https://fonts.googleapis.com; font-src https://fonts.gstatic.com |
| Google Analytics | script-src https://www.googletagmanager.com; connect-src https://www.google-analytics.com |
| Stripe | script-src https://js.stripe.com; frame-src https://js.stripe.com; connect-src https://api.stripe.com |
| Inline styles (CSS-in-JS) | style-src 'unsafe-inline' — acceptable tradeoff for style-src |
| fetch() to API | connect-src https://api.example.com |
| WebSocket | connect-src wss://realtime.example.com |