Skip to main content

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

DirectiveControlsExample
default-srcFallback for other directives'self'
script-srcLoading and executing JavaScript'self' 'nonce-abc123'
style-srcLoading and applying CSS'self' 'unsafe-inline'
img-srcSources from which images load'self' data: https://cdn.example.com
connect-srcDestinations for fetch / XHR / WebSocket'self' https://api.example.com
frame-ancestorsOrigins allowed to embed in an iframe'none'
form-actionForm submission destinations'self'

Nonce-Based and Hash-Based Allowlisting

There are two ways to allow inline scripts: the nonce method and the hash method.

Nonce 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.

Hash method

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

Assess the current state with Report-OnlyAnalyze violation reportsTighten the policy in stagesManage exceptions with nonce / hashSwitch to the production headerContinuously monitor reports

Common Mistakes When Deploying

Carelessly allowing unsafe-inline

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.

Abusing wildcards

Specifying * in script-src allows scripts to be loaded from any domain. Enumerate the permitted domains individually.

Overlooking third parties

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.

Related Terms

Was this article helpful?

XHatena