Security headers for vibe-coded apps: copy-paste Netlify and Vercel configs
Add five headers to every response: Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options: DENY (or CSP frame-ancestors), Referrer-Policy and a Content-Security-Policy. On Netlify they go in a _headers file in your publish folder. On Vercel they go in vercel.json (or next.config.js for Next.js). Start the CSP in Report-Only mode, fix what it flags in the browser console, then switch it to enforcing. Copy-paste configs are below.
What each header does, in one line
| Header | What it stops |
|---|---|
Strict-Transport-Security | Browsers falling back to plain HTTP on later visits (MDN) |
Content-Security-Policy | Injected scripts loading or sending data to places you didn't approve (MDN) |
X-Frame-Options / frame-ancestors | Other sites framing your pages for clickjacking |
X-Content-Type-Options: nosniff | Browsers guessing file types and running something as script |
Referrer-Policy | Full URLs (which may contain tokens or IDs) leaking to other sites |
Permissions-Policy | Pages using the camera, microphone or location unless you allow it |
The OWASP Secure Headers Project keeps a longer reference if you want to go further.
Netlify: _headers
Create a plain text file called _headers (no extension) that ends up in your publish directory. For Vite apps that means putting it in public/_headers so it's copied into dist/ (Netlify docs). Replace YOUR-PROJECT with your Supabase project ref, and drop the Stripe parts if you don't use Stripe.
Vercel: vercel.json
Put this in vercel.json at your project root (Vercel docs).
Next.js: next.config.js
For Next.js on any host that runs the Next server, you can use the headers() config. With output: 'export' (a static export), this doesn't run, so set the headers at your host instead.
Rolling out CSP without breaking your app
- Start with
Content-Security-Policy-Report-Only(as in the configs above). The browser reports violations in the console but blocks nothing. - Click through your app: sign in, pay, upload, use every feature. Note each "violates the following Content Security Policy directive" message in the console.
- Add the domains you actually use (analytics, fonts, Supabase storage, Stripe). Stripe publishes the domains its scripts need in its security guide.
- When the console is clean, rename the header to
Content-Security-Policyto enforce it. - Avoid adding
'unsafe-eval', and'unsafe-inline'for scripts. If something needs them, ask your AI coder for a different approach first.
Check it worked
- Run
curl -sI https://your-app.comand look for the headers in the response. - Or use MDN HTTP Observatory or securityheaders.com for a graded check.
- If a header doesn't appear: on Netlify,
_headersonly applies to files Netlify serves itself, so functions and proxied responses set their own (Netlify docs). Also check the file really landed in the publish folder.
Built-in hosting on some AI app builders may not let you set custom headers. If yours doesn't, check its docs, or deploy the same code to a host that does (Netlify, Vercel, Cloudflare Pages).
FAQ
Which security headers should every web app have?
At minimum: Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options: nosniff, a Referrer-Policy such as strict-origin-when-cross-origin, and frame protection through X-Frame-Options: DENY or the CSP frame-ancestors directive. Permissions-Policy is a good extra.
Where do I put security headers on Netlify?
In a plain text file named _headers in your site's publish directory (for Vite apps, put it in public/ so it's copied into dist/), or in [[headers]] blocks in netlify.toml.
Where do I put security headers on Vercel?
In vercel.json at the project root under a headers array, or for Next.js apps in the async headers() function in next.config.js.
Will a Content-Security-Policy break my app?
It can, if it blocks a script, API or font your app needs. Roll it out as Content-Security-Policy-Report-Only first, fix the violations shown in the browser console, then switch to the enforcing header.
How do I test my security headers?
Run curl -sI against your URL to see the raw headers, or use MDN HTTP Observatory or securityheaders.com for a graded report.
Sources
- MDN: Content-Security-Policy
- MDN: Strict-Transport-Security
- OWASP Secure Headers Project
- Netlify: Custom headers
- Vercel: vercel.json
- Next.js: headers()
- Stripe: Security guide (CSP)
This guide is general information, not a security audit. Platforms change, so check the linked docs for current details. Spotted something out of date? Email hello@milokits.com.