Build a robust Content Security Policy header to protect your web applications against XSS, data injection, and other code-execution attacks. Select directives, define allowed sources, and generate a production-ready CSP string with one click. Includes preset templates and detailed guidance for every directive.
Content Security Policy (CSP) is a security standard introduced by the W3C to prevent cross-site scripting (XSS), clickjacking, and other code-injection attacks. CSP works by defining a whitelist of trusted sources from which a browser may load resources such as scripts, stylesheets, images, fonts, and media. When a browser receives a CSP header from a server, it enforces these rules, blocking any resource that does not match the defined policy.
CSP is one of the most effective defenses against XSS — the OWASP Top 10 consistently ranks injection attacks among the most critical web vulnerabilities. By deploying a strict CSP, you can dramatically reduce the attack surface of your web application, even if other defenses (like input sanitization) fail.
A CSP header is delivered via HTTP:
Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.example.com; style-src 'self' 'unsafe-inline';
This tells the browser: "Only load resources from the same origin, except scripts from apis.example.com, and allow inline styles."
'self', https://cdn.example.com, 'unsafe-inline', etc.).
.htaccess, Nginx, Apache, or directly in your application's HTTP responses).
When a browser receives a CSP header, it parses the policy and constructs a set of rules. For each resource fetch (script, style, image, font, etc.), the browser checks the resource's URL against the appropriate directive. If the URL matches the allowed sources, the resource is loaded; otherwise, the browser blocks it and, if configured, sends a violation report to the specified report-uri or report-to endpoint.
CSP supports several source expression types:
'self' — Matches the same origin (protocol, domain, and port).
'unsafe-inline' — Allows inline scripts or styles (use with caution; this weakens CSP).
'unsafe-eval' — Allows eval() and similar dynamic code execution (strongly discouraged).
'nonce-' — A cryptographic nonce that allows specific inline scripts or styles.
'strict-dynamic' — Allows scripts that are loaded by a trusted script (nonce-based or hash-based).
'sha256-<hash>' — Allows inline scripts or styles that match a specific hash.
https: — Matches any HTTPS URL.
http://*.example.com — Wildcard matching for subdomains.
Modern CSP (Level 3) introduces the 'strict-dynamic' keyword, which simplifies policy management for complex applications by allowing scripts that are loaded from trusted sources to also load additional scripts without explicit whitelisting. This reduces the need for large whitelists and improves security.
Content-Security-Policy-Report-Only first to monitor violations without breaking your application.
'unsafe-inline' and 'unsafe-eval' — These keywords significantly weaken CSP. Use nonces or hashes instead.
'strict-dynamic' for modern applications — This allows trusted scripts to load additional scripts, simplifying whitelist management.
base-uri to 'self' — Prevents attackers from changing the base URL for relative paths.
object-src to 'none' — Blocks plugins (Flash, Java) which are common vectors for attacks.
upgrade-insecure-requests — Forces all HTTP requests to be upgraded to HTTPS, helping to maintain a secure connection.
frame-ancestors to 'self' — Prevents clickjacking by restricting which domains can embed your page.
report-uri or report-to to receive violation reports and continuously refine your policy.
frame-ancestors), data injection, and mixed content issues.
A major online banking platform deployed a strict CSP with script-src 'strict-dynamic' and nonce-based inline scripts. Within weeks, they observed a 94% reduction in XSS-related security incidents. The policy also blocked several attempted data exfiltration attacks via malicious third-party scripts. The CSP was deployed in report-only mode for two weeks, during which the security team refined the policy based on real-world traffic patterns before enforcing it.
Key takeaway: A well-tuned CSP not only prevents attacks but also provides visibility into third-party script behavior, enabling better supply-chain security.
A fast‑growing e‑commerce platform used CSP to lock down its payment checkout page. By setting frame-ancestors 'none' and object-src 'none', they eliminated clickjacking and plugin‑based attacks. The policy also blocked a third‑party analytics script that was inadvertently loading resources from an insecure CDN. The team used the generator to quickly iterate on their policy, reducing the time to deploy a secure header from days to minutes.
| Directive | Purpose | Example Value | Risk if omitted |
|---|---|---|---|
default-src
|
Fallback for all resource types | 'self' https: | High — no base policy |
script-src
|
JavaScript sources | 'self' 'strict-dynamic' | Critical — XSS vector |
style-src
|
CSS sources | 'self' 'unsafe-inline' | High — CSS injection |
img-src
|
Image sources | 'self' data: https: | Medium — image exfiltration |
connect-src
|
Fetch, XHR, WebSocket sources | 'self' https://api.example.com | Medium — data exfiltration |
frame-src
|
Iframe sources | 'self' https://trusted.com | Medium — phishing via iframe |
object-src
|
Plugins (Flash, Java) | 'none' | High — plugin vulnerabilities |
base-uri
|
Base URL for relative paths | 'self' | High — base tag manipulation |
form-action
|
Form submission targets | 'self' | Medium — phishing via forms |
frame-ancestors
|
Parent domains for embedding | 'self' | High — clickjacking |
upgrade-insecure-requests
|
Upgrade HTTP to HTTPS | (boolean) | Medium — mixed content |
block-all-mixed-content
|
Block mixed (HTTP) content on HTTPS | (boolean) | Medium — mixed content |
report-uri is the older, more widely supported directive that specifies a URL where violation reports are sent via POST requests. report-to is the newer directive that works with the Reporting API, allowing for more flexible reporting configurations. Use both for maximum compatibility: report-uri /csp-report; report-to default;
'unsafe-inline' if at all possible. It allows any inline script or style to execute, which largely defeats the purpose of CSP. Use nonces ('nonce-...') or hashes ('sha256-...') to safely permit specific inline code. If you must use 'unsafe-inline', combine it with 'strict-dynamic' and a nonce to maintain security.
Header set Content-Security-Policy "your-policy-here" to your .htaccess or virtual host config. For Nginx, use add_header Content-Security-Policy "your-policy-here";. For Node.js (Express), use helmet.contentSecurityPolicy(). For other platforms, consult your server documentation.
'strict-dynamic' is a CSP keyword that allows scripts loaded from trusted sources (via nonce or hash) to load additional scripts without needing to be individually whitelisted. It is ideal for modern single‑page applications (SPAs) that dynamically load scripts, as it reduces the size of your whitelist and improves security by trusting only the initial script loader.
script-src 'self' https://cdn.example.com; allows scripts from both your origin and the CDN. Be careful to only include CDNs you trust, as a compromised CDN could inject malicious code.