A practical guide to Content-Security-Policy
CSP is the strongest defence against cross-site scripting. Learn what it controls, how to roll it out safely with report-only, and how to avoid unsafe-inline.
A Content-Security-Policy (CSP) tells the browser exactly which sources of script, style, images and other resources are allowed to load. If an attacker injects a <script> tag, a good CSP stops it running — which is why CSP is the single most effective mitigation for cross-site scripting (XSS).
The shape of a policy
A policy is a set of directives, each naming allowed sources. default-src is the fallback; more specific directives override it.
Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'Avoid 'unsafe-inline'
The moment you allow 'unsafe-inline' for scripts, CSP stops protecting you from injected scripts — the whole point. Instead, move inline scripts to files served from your own origin, or authorise the specific inline blocks you control with a hash or a per-request nonce.
script-src 'self' 'sha256-BASE64HASH='
# or
script-src 'self' 'nonce-RANDOMPERREQUEST'Roll it out with report-only
Don't ship a strict policy blind. Deploy it in report-only mode first: the browser reports what would have been blocked without actually blocking anything, so you can find legitimate resources you forgot before enforcing.
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-reportCommon pitfalls
- Third-party widgets that inject inline script or load from many hosts — allowlist exactly what they need, nothing broader.
- connect-src forgetting your analytics or API endpoints, silently breaking requests.
- Edge providers injecting their own inline scripts that your hash doesn't cover — either disable that feature or account for it.
- Using a nonce that isn't actually random per response — a fixed nonce is no better than unsafe-inline.
How to fix it
- Inventory what your pages load (script, style, images, fonts, connections, frames).
- Write a report-only policy and watch the reports for a few days.
- Tighten until there are no legitimate violations, then switch the header to enforcing.
- Re-scan and keep object-src 'none', base-uri 'self' and frame-ancestors locked down.
Glossary
- Directive
- One rule inside a CSP, e.g. script-src, naming the allowed sources for a resource type.
- Nonce
- A random token generated per response and placed on both the header and the trusted inline tag to authorise it.
- XSS
- Cross-site scripting: running attacker-controlled JavaScript in a victim's browser in the context of your site.