Content Security Policy Explained (Without Tears)
What CSP actually does, why most policies fail open, a starter policy you can ship today, and how to roll it out report-only without breaking things.
Short answer
CSP tells the browser which sources may load scripts, styles, images, and more. It is the strongest browser-side control against injected scripts when you enforce it carefully - start report-only, then tighten.
What CSP is for
A Content-Security-Policy is an allowlist the browser enforces on every page load. Injected script that violates the policy simply does not run. That is a different layer from server auth - it protects the client even when something else went wrong.
XSS still needs fixing at the source. CSP is the seatbelt that still helps when a bug slips through.
Why most policies fail open
unsafe-inline and unsafe-eval in script-src undo much of the value. They are common because a strict CSP takes iteration across real pages, third-party widgets, and legacy templates.
That is why report-only mode exists: learn what your real pages load before you break checkout. Shipping enforce with a wide-open policy is theatre.
A sane rollout
Ship Content-Security-Policy-Report-Only with a tight default-src. Collect violations for a week. Fix legitimate sources (or drop dead scripts). Then switch to enforcing CSP and re-scan.
Framework sites often need nonces or hashes. Budget time for that. Do not give up and re-open the policy to "anything goes" just to silence the console.
Not a silver bullet
CSP does not replace HTTPS, authentication, or patching. It is one strong control in a set. Pair it with HSTS, framing controls, and nosniff so a single missing header does not define your whole posture.
When a scan still complains, read the violated directive. Blindly adding hosts to the allowlist is how CSP becomes wallpaper.
Config to copy
Content-Security-Policy-Report-Only: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'
Paste carefully. Test on staging first if the setting can lock users out.
What to do this week
- Enable CSP Report-Only on staging with a tight default-src.
- Collect one week of violations; fix real sources or remove dead scripts.
- Flip to enforce on production after the noise dies down.
- Re-scan and keep the policy next to your header deploy notes.
Report-only first. Enforce second. Never ship unsafe-inline forever.
Update log (1)
2026-05-02Editorial form rewrite for length and uniqueness.
Sources + verification
Practical guidance based on mainstream browser behavior, common reverse-proxy configuration, and widely published RFCs and vendor docs. Verify on your own stack with curl, browser devtools, and a re-scan after each change.