CSP - Content Security Policy
About 2 min read
CSP (Content Security Policy) is a security mechanism that declares, via an HTTP response header, the permitted origins of resources allowed to execute on a web page. It was standardized at the W3C in 2012 as a defensive layer that greatly reduces the damage from cross-site scripting (XSS). By having the server instruct the browser that "only scripts from this domain may run on this page," it blocks the execution of malicious scripts injected by an attacker at the browser level.
Its Role as an XSS Countermeasure
The basics of XSS prevention are input sanitization and output escaping, but these measures are prone to gaps caused by developer mistakes. CSP functions as a "last line of defense" that complements these measures. Even if an escaping oversight allows attack code to slip into the HTML, a correctly configured CSP causes the browser to refuse to execute that script. Combining secure coding with CSP achieves defense in depth.
Key Directives
| Directive | Controls | Example |
|---|---|---|
| default-src | Fallback for other directives | 'self' |
| script-src | Loading and executing JavaScript | 'self' 'nonce-abc123' |
| style-src | Loading and applying CSS | 'self' 'unsafe-inline' |
| img-src | Sources from which images load | 'self' data: https://cdn.example.com |
| connect-src | Destinations for fetch / XHR / WebSocket | 'self' https://api.example.com |
| frame-ancestors | Origins allowed to embed in an iframe | 'none' |
| form-action | Form submission destinations | 'self' |
Nonce-Based and Hash-Based Allowlisting
There are two ways to allow inline scripts: the nonce method and the hash method.
The server generates a random value (nonce) for each request and embeds the same value in both the CSP header and the script tag. Only scripts whose values match are executed. This suits dynamic pages, and frameworks such as Next.js and Rails support automatic nonce generation.
A hash value such as SHA-256 is computed from the contents of the inline script and listed in the CSP header. If even one byte of the script content changes, the hash will not match and it will not execute. This suits static scripts, but the hash must be recomputed each time the content changes.
Monitoring with report-uri / report-to
CSP includes a mechanism for reporting policy violations to the server. report-uri (legacy spec) or report-to (new spec) directive lets you specify the report destination, after which the browser sends a JSON-format report each time it detects a policy violation. First, collect reports only with the Content-Security-Policy-Report-Only header and confirm that existing functionality is not broken before migrating to production enforcement; this is the safe deployment procedure.
The CSP Deployment Flow
Common Mistakes When Deploying
Adding 'unsafe-inline' just because inline scripts won't run nearly nullifies CSP's XSS protection. Migrating to the nonce method is the correct answer.
Specifying * in script-src allows scripts to be loaded from any domain. Enumerate the permitted domains individually.
Forgetting third-party scripts such as ads, analytics, and chat widgets will cause features to break in production.
CSP is a foundational web security technology alongside WAF and SSL/TLS. web security books on Amazon are recommended for systematic learning. Also see Browser Extension Security, Browser Password Safety, and the Startup Security Checklist.
Was this article helpful?