High severity

How to fix a missing Content-Security-Policy header

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.

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.

How to check

  1. 01Open your site in Chrome, then open DevTools → Network tab.
  2. 02Reload the page and click the first (document) request.
  3. 03Under Response Headers, look for `content-security-policy`.
  4. 04If it is missing or set to `default-src *`, the header is not protecting you.

Or let SafeToShip check it for you in 60 seconds:

How to fix it

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';"
      }]
    }];
  }
};

Vercel (vercel.json)

If you deploy to Vercel without a framework, add a headers rule in vercel.json.

{
  "headers": [{
    "source": "/(.*)",
    "headers": [{
      "key": "Content-Security-Policy",
      "value": "default-src 'self'; script-src 'self' 'unsafe-inline'; frame-ancestors 'none';"
    }]
  }]
}

Generic (any host)

Send this response header from your CDN, reverse proxy, or server. Cloudflare, Netlify, and Fastly all have header-injection settings.

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'

AI prompt

Copy-paste into your AI tool

Paste this prompt into Cursor, Lovable, Bolt, v0, or Claude Code and it will walk through the fix for your specific codebase.

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

Scan your site for this and 50+ other issues

Free scan. Results in 60 seconds. No account required.