Content-Security-Policy (CSP): what it is and how to add one
Content-Security-Policy (CSP) is an HTTP response header that tells the browser which sources of script, style, and other content it is allowed to load and execute. A good CSP is one of the strongest defenses against cross-site scripting (XSS).
What it is
CSP is a browser-enforced allowlist. When your server sends a Content-Security-Policy header, the browser refuses to load or execute anything that the policy doesn't explicitly permit — inline scripts, third-party domains, eval(), and so on.
A policy is a list of directives. For example, script-src 'self' says "only run JavaScript served from my own origin," while object-src 'none' blocks legacy plugins entirely.
Why it matters
Without CSP, any HTML-injection or XSS bug lets an attacker run arbitrary JavaScript in your users' browsers — stealing sessions, rewriting the page, or exfiltrating data.
A weak CSP is almost as bad as none. 'unsafe-inline' re-allows the inline scripts attackers rely on, and a wildcard source like script-src * lets script load from anywhere, defeating the point.
How to fix it
Set the header in next.config.js so it applies to every response. Start strict and loosen only where needed.
// next.config.js
const csp = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"base-uri 'none'",
"frame-ancestors 'none'",
"object-src 'none'",
].join("; ");
module.exports = {
async headers() {
return [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: csp }] }];
},
};If you need inline scripts, generate a per-request nonce and add it to both the script tag and the policy (script-src 'self' 'nonce-<value>') instead of using 'unsafe-inline'.
base-uri 'none', frame-ancestors 'none', and object-src 'none' close common bypasses (base-tag injection, clickjacking, and plugin embedding) and are safe defaults for most apps.
FAQ
Does a CSP slow my site down?
No. CSP is just a header the browser evaluates; it adds no measurable latency. The real cost is the engineering work to remove inline scripts.
What is the difference between Content-Security-Policy and X-Frame-Options?
X-Frame-Options only controls framing (clickjacking). CSP's frame-ancestors directive supersedes it and CSP also governs scripts, styles, images, and more.
Is your app affected?
AppSafe checks for this and dozens of other issues in one free scan.
Scan my app free