A Content Security Policy tells the browser which sources of script, style, and other resources are permitted. Its practical value is containment: when a cross-site scripting bug exists — and eventually one will — a good policy prevents it from loading attacker-controlled script or exfiltrating data to an arbitrary destination.
Deploy in report-only mode first
Use the report-only header with a reporting endpoint and leave it for a week or two. You will discover every inline script, every third-party resource, and every injected element you had forgotten. Enforcing before this exercise is how sites break, and how CSP acquires a reputation for being painful.
The directives that matter most
- default-src as a restrictive baseline, then loosen specific directives deliberately.
- script-src, which carries most of the security value.
- frame-ancestors to control who may embed your site — this supersedes X-Frame-Options.
- connect-src to limit where the page may send data, which constrains exfiltration.
- object-src set to none, since legacy plugin content is essentially never needed.
Inline script is the usual obstacle
Permitting unsafe-inline removes most of the benefit, because injected script is inline script. The correct approach is a per-request nonce applied to your own inline scripts, or hashes for a small fixed set. Where a third-party tag demands unsafe-inline, that is a reason to reconsider the tag rather than to weaken the policy globally.
Keep collecting reports after enforcement
Violation reports continue to be useful once enforcing: they reveal browser extensions injecting content, third parties changing their behaviour, and, occasionally, an actual injection attempt. Route them somewhere a person periodically reads.
The other headers worth setting at the same time
Strict-Transport-Security to enforce HTTPS, X-Content-Type-Options to prevent MIME sniffing, Referrer-Policy to limit what you leak to third parties, and Permissions-Policy to disable device features your site does not use. Together with CSP this is a short configuration block that removes several categories of attack.
What CSP does not do
It does not fix the underlying vulnerability. Output encoding, input validation, and framework escaping remain the primary defences. Treat CSP as the control that limits the blast radius of the bug you have not found yet.