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, which is 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 and 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.