Missing CSP header on Next.js
Your site is missing a Content-Security-Policy (CSP) header. CSP tells the browser which scripts, styles, and images are allowed to load, blocking malicious injections like XSS. Without it, a single vulnerable dependency or user input field can be used to steal sessions, redirect users, or deface your app. The fix is to send a CSP header from your hosting platform or framework — one line in Next.js config or a vercel.json rule. Start with a permissive policy in report-only mode, then tighten it.
The fix for Next.js
Next.js (next.config.js)
Add a headers() function that applies a baseline CSP to all routes. Tighten allowed origins as you identify them.
module.exports = {
async headers() {
return [{
source: '/:path*',
headers: [{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.supabase.co https://api.stripe.com; frame-ancestors 'none';"
}]
}];
}
};Why it matters
XSS is the single most common web vulnerability. CSP is the browser-level backstop that stops XSS even when your code has a bug. AI-generated apps often paste user input directly into pages, which makes CSP the cheapest defense you can ship.
Confirm the fix worked
Scan your Next.js site to confirm this finding is gone.
AI prompt
Apply across your codebase
Paste this into Cursor, Lovable, Bolt, v0, or Claude Code.
Add a baseline Content-Security-Policy header to my app. It should apply to every route. Allow scripts and styles from the same origin plus any CDNs I am already loading (check my code for <script src="..."> and <link href="..."> tags). Allow images from https: and data: URIs. Block framing with frame-ancestors 'none'. Allow API calls to any Supabase, Stripe, or third-party domain I am already calling from client code. Return the exact code change needed for my framework and paste the final header value so I can verify it in DevTools.FAQ
Frequently asked questions
- Will CSP break my site?
- It can, if you load scripts from a domain the policy does not allow. Start in report-only mode by sending `Content-Security-Policy-Report-Only` instead of `Content-Security-Policy`. The browser will log violations without blocking them. Watch the console for a week, then switch to enforcing mode.
- Should I use 'unsafe-inline' or a nonce?
- Nonces are stronger but harder to set up. If you are shipping fast, `'unsafe-inline'` for scripts and styles is acceptable as a starting point. Graduate to nonces once you are tracking down any inline scripts your framework generates.
- Does Next.js have CSP built in?
- Not automatically. Next 13+ supports nonces via middleware, but you still have to opt in. The fastest path is the `headers()` config above. Vercel-hosted Next.js apps can also set headers in `vercel.json`.
Related fix guides
Fix these too
Missing X-Frame-Options
Without X-Frame-Options or CSP frame-ancestors, attackers can embed your site in an invisible iframe to trick users into clicking things. Here is the fix.
Read moreMissing HSTS header
HSTS tells browsers to always use HTTPS for your site. Without it, users can be downgraded to HTTP and have sessions stolen. Here is how to add HSTS on Vercel, Next.js, and other hosts.
Read moreMissing Permissions-Policy
Permissions-Policy controls which browser features (camera, microphone, geolocation) your site and its iframes can use. Default-allow is unsafe — lock it down.
Read moreConcepts
Glossary
Content Security Policy
CSP is a browser feature that tells your site which scripts, styles, and images are allowed to run. It is the main defense against cross-site scripting (XSS).
Read moreCross-Site Scripting
XSS is an attack where malicious JavaScript gets injected into your site and runs in other users' browsers. CSP and input sanitization are the main defenses.
Read moreSecurity Headers
A set of HTTP response headers that harden your site against common web attacks. Every site should send all six.
Read moreFree tools