HTTP Security Headers for Vibe-Coded Apps: A Practical Guide
Of all the findings that turn up in scans of AI-generated apps, the missing security-header set is both the most common and the least expensive to fix. One 2026 sample found the standard set absent in the large majority of apps scanned. Code generators do not add headers because headers are not a feature; nothing in the UI breaks without them.
They matter because they decide how much damage a small client-side bug can do.
The set worth having
| Header | What it prevents |
|---|---|
Content-Security-Policy |
Injected scripts executing, data exfiltration to unknown hosts |
Strict-Transport-Security |
Downgrade to plain HTTP, cookie interception |
X-Content-Type-Options: nosniff |
A user upload being interpreted as JavaScript |
Referrer-Policy |
Leaking full URLs — including tokens in paths — to third parties |
Permissions-Policy |
Silent access to camera, microphone, geolocation |
X-Frame-Options / CSP frame-ancestors |
Clickjacking your own UI |
A starting policy
Content-Security-Policy: default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' data:;
connect-src 'self' https://*.supabase.co;
frame-ancestors 'none';
base-uri 'self';
object-src 'none'
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()Two notes. style-src 'unsafe-inline' is a concession most Tailwind and component-library setups still need; keep it out of script-src, which is where it actually hurts. And connect-src must list every API host you talk to — your database, your analytics, your error reporter — or requests fail silently in production while working in dev.
Roll it out without breaking the app
- Ship
Content-Security-Policy-Report-Onlywith the policy above. - Watch violation reports and the browser console for a few days of real traffic.
- Add the hosts you genuinely need — one at a time, not a wildcard.
- Switch the header to enforcing.
Do the other five headers immediately; they almost never break anything.
Verify what you actually send
Config files lie. Check the response:
curl -sI https://your-app.example | rg -i 'content-security|strict-transport|x-content-type|referrer|permissions|frame'Check an API route and an error page too, not just the homepage — header middleware often misses both.
What headers do not do
They do not authorise anything. If your database is readable with a public key, a perfect content security policy changes nothing, because the attacker does not need your JavaScript. Fix access rules first, then harden the delivery layer.
Sentrail records the headers your deployment actually returns as part of the launch-readiness evidence, so "we added a CSP" becomes something you can prove rather than something you remember doing.
