Content Security Policy (CSP) header not set, or missing CSP directives
A scanner says Content Security Policy (CSP) header not set, or lists missing CSP directives? Send a Content-Security-Policy response header and set the directives default-src doesn't cover.
Short answer
Content Security Policy header not set means the response for your page has no Content-Security-Policy header. Add it where your host sets response headers, such as the headers list in vercel.json or a _headers file on Netlify. Start with default-src 'self'. Then set frame-ancestors, form-action and base-uri yourself, because default-src only covers fetch directives.
Reviewed October 28, 2026
What it means in plain English
Content-Security-Policy is a response header that tells the browser where the page may load scripts, styles, images, and other resources from. Vercel's docs describe it as a defense against cross-site scripting (XSS): "Any content not loaded from these approved sources will be blocked."
A scanner reports CSP header not set when the document response has no Content-Security-Policy header. It reports missing CSP directives when a policy exists but leaves something out.
The directives that are easy to miss are the ones default-src does not cover. MDN says "default-src is a fallback for all other fetch directives." base-uri (a document directive), form-action and frame-ancestors (navigation directives) are not fetch directives. MDN's frame-ancestors page says it "does not fall back to the default-src setting. A policy that declares default-src 'none' still allows the resource to be embedded by anyone."
Likely causes
- The host was never told to send the header. Most AI-built apps ship as static files with no headers of their own.
- The policy was put in a
<meta>tag. MDN saysframe-ancestors"is not supported in the<meta>element." - The policy sets
default-srconly, sobase-uri,form-action, andframe-ancestorsare unset.
How to fix it, step by step
- Open the live page, then the browser's network panel, and read the response headers for the document. Look for
Content-Security-Policy. - List the outside hosts the page really uses: analytics, fonts, chat widgets, your Supabase project URL, payment scripts.
- Start in report-only mode. Vercel's best practice: "start with the
Content-Security-Policy-Report-Onlyheader" and switch to enforcing "once you know your policy won't break any features." - Write the policy. A starting point built from MDN's directives:
Content-Security-Policy: default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'
Add each host from step 2 to the directive that needs it, for example script-src 'self' cdn.example.com or connect-src 'self' https://yourproject.supabase.co. Vercel advises listing specific hosts rather than *.
-
Avoid
'unsafe-inline'and'unsafe-eval'. MDN says that once a policy hasdefault-srcorscript-src, inline scripts andeval()are blocked. Vercel recommends nonces or hashes for inline code you need. -
Add the header on your host. Where to add a response header:
- Vercel: the
headerslist invercel.json, with asourcepattern such as/(.*)and a list ofkeyandvaluepairs. - Netlify: a plain text
_headersfile in the publish directory, or[[headers]]innetlify.toml. Netlify says custom headers don't apply to content handled by a function or edge function, such as a server-rendered page, or to proxied content. Those must return the header themselves. - Your own server: set it in the web server config. MDN's X-Frame-Options page shows Apache, Nginx, and IIS examples.
- Vercel: the
-
Redeploy, check for blocked resources in the console, then rename the header to
Content-Security-Policyto enforce it.
How to check it worked
- The document response includes
Content-Security-Policywithdefault-src,base-uri,form-action, andframe-ancestors. - The browser console shows no CSP violations while you click through the app, sign in, and pay.
For HSTS and the other headers in one place, see Missing Content-Security-Policy, HSTS, or X-Frame-Options.
Questions people ask
What does Content Security Policy header not set mean?
Your page response has no Content-Security-Policy header, so the browser has no policy limiting where the page may load scripts and other resources from.
Which CSP directives are commonly missing?
The ones default-src does not cover. MDN lists default-src as the fallback for fetch directives only, so base-uri, form-action and frame-ancestors need their own entries.
Can I set a Content Security Policy with a meta tag instead?
Partly. MDN shows a meta tag example, but the frame-ancestors directive is not supported in the meta element, so a response header is the complete fix.
Will adding a CSP break my site?
It can block scripts, styles or images from hosts the policy does not list. Vercel recommends starting with Content-Security-Policy-Report-Only, which reports violations without blocking, then switching to enforcing mode.
Sources
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy (opens in a new tab)
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors (opens in a new tab)
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP (opens in a new tab)
- https://vercel.com/docs/headers/security-headers (opens in a new tab)
- https://vercel.com/docs/project-configuration/vercel-json (opens in a new tab)
- https://docs.netlify.com/manage/routing/headers/ (opens in a new tab)
Related fixes
Keep going on your own.
The guides stay free. A deep leak report is $15. Fix packs are $24, or $49 for all three. There is no done-for-you repair.