HTTP headers · Response
Content-Security-Policy
Content-Security-Policy restricts which sources a page may load and execute.
Key facts
| Type | Response |
|---|---|
| Key directives | <code>default-src</code>, <code>script-src</code> |
| Navigation | <code>frame-ancestors</code>, <code>form-action</code> |
| Nonces | <code>'nonce-...'</code> |
| Hashes | <code>'sha256-...'</code> |
| Report only | <code>Content-Security-Policy-Report-Only</code> |
| Inline | Blocked without nonce, hash or unsafe-inline |
| Standard | CSP Level 3 |
An allowlist for the page
CSP tells the browser which origins may supply scripts, styles, images, fonts, frames and connections. default-src is the fallback; specific directives override it. A strict policy blocks injected inline scripts, which removes most cross-site scripting payloads even when an injection point exists.
The strongest common pattern is a per-response nonce on every legitimate script tag plus 'strict-dynamic' for scripts those scripts load. Hashes work for static inline code but require updating the policy whenever the code changes.
Rolling it out without breaking the site
Start with Content-Security-Policy-Report-Only and collect violation reports. Then move directives into enforcement one at a time. Inline event handlers, eval, third-party widgets and data: images are the usual breakages.
CSP is defence in depth, not a substitute for output encoding. frame-ancestors replaces X-Frame-Options for clickjacking, and form-action limits where forms can submit, which blocks a common exfiltration path.
Frequently asked questions
Does CSP stop all XSS?
No. It stops inline and unauthorized script execution, but DOM-based sinks, allowed origins and misconfigurations can still be exploited.
Can I set CSP with a meta tag?
Some directives work in meta, but frame-ancestors and reporting do not. A response header is the reliable place.