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 says frame-ancestors "is not supported in the <meta> element."
  • The policy sets default-src only, so base-uri, form-action, and frame-ancestors are unset.

How to fix it, step by step

  1. Open the live page, then the browser's network panel, and read the response headers for the document. Look for Content-Security-Policy.
  2. List the outside hosts the page really uses: analytics, fonts, chat widgets, your Supabase project URL, payment scripts.
  3. Start in report-only mode. Vercel's best practice: "start with the Content-Security-Policy-Report-Only header" and switch to enforcing "once you know your policy won't break any features."
  4. 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 *.

  1. Avoid 'unsafe-inline' and 'unsafe-eval'. MDN says that once a policy has default-src or script-src, inline scripts and eval() are blocked. Vercel recommends nonces or hashes for inline code you need.

  2. Add the header on your host. Where to add a response header:

    • Vercel: the headers list in vercel.json, with a source pattern such as /(.*) and a list of key and value pairs.
    • Netlify: a plain text _headers file in the publish directory, or [[headers]] in netlify.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.
  3. Redeploy, check for blocked resources in the console, then rename the header to Content-Security-Policy to enforce it.

How to check it worked

  • The document response includes Content-Security-Policy with default-src, base-uri, form-action, and frame-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

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.

See products