HeHeedza

Missing security headers

Which response headers matter on an AI-built app, which ones are noise, and a small snippet to add them.

A short list, not a scanner dump

Most generated apps send only the headers their host adds by default. You do not need a perfect score. You do want five of them on the HTML response: Content-Security-Policy, Strict-Transport-Security (on HTTPS), X-Frame-Options or CSP frame-ancestors, X-Content-Type-Options: nosniff, and Referrer-Policy. Permissions-Policy is worth adding once the first five exist.

X-XSS-Protection is obsolete. A missing favicon is not a vulnerability. A missing CSP will not sink you by itself, but it is the header that limits damage when a secret or a third-party script ends up in the page.

What each one is for

HSTS tells the browser to keep using HTTPS, so a later visit cannot be downgraded. Set it only after the site really is HTTPS everywhere, including subdomains if you include includeSubDomains.

X-Frame-Options: DENY, or CSP frame-ancestors 'none', stops another site from embedding your login page and clicking through it. nosniff stops a browser from treating a user upload as HTML. Referrer-Policy: strict-origin-when-cross-origin keeps full paths from leaking when someone clicks out to Stripe or a docs site.

Where to set them

On Cloudflare, put the headers in a _headers file or the Workers assets config. On Vercel, vercel.json or next.config. On Netlify, netlify.toml. A host-level header is better than a meta tag, because meta tags cannot set HSTS or frame-ancestors reliably.

A Cursor prompt: “Add security headers to the HTML responses: Content-Security-Policy with a default-src that matches the scripts this app actually loads, Strict-Transport-Security, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, and X-Frame-Options DENY. Do not break the Stripe.js or Supabase domains the app already calls.” Start the CSP in report-only if you are unsure which domains the app loads.

Heedza reads these headers on the homepage response during the free scan. Missing ones lower the grade a little. An exposed .env or a live secret key lowers it a lot more.