How to add a Content-Security-Policy to a vibe-coded app
Medium
A Content-Security-Policy (CSP) header tells the browser which sources of scripts, styles and connections are allowed. Without one, any injected script runs with full access to your users' sessions.
Why it matters
If an attacker finds a way to inject HTML (via user content, a vulnerable package or a compromised third-party script), CSP is the backstop that stops it from running or sending data elsewhere.
Quick fix
- Add a Content-Security-Policy header via vercel.json, _headers or next.config.js.
- Start with Content-Security-Policy-Report-Only to see what would break, then enforce.
- Allow your API/Supabase domains in connect-src.
Step by step
Vercel (vercel.json)
Adjust connect-src and script-src to the domains your app really uses.
// vercel.json (works for Vite/React apps deployed on Vercel)
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
{ "key": "Content-Security-Policy", "value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.supabase.co wss://*.supabase.co; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" }
]
}
]
}Roll out safely
Deploy the same value as Content-Security-Policy-Report-Only first, open your app, and check the browser console for violations. Then switch to the enforcing header.
Next.js
Next.js injects inline scripts, so a strict CSP needs nonces generated in middleware. Follow the official Next.js CSP guide.
Prompt for your AI builder
Paste this into Lovable, Bolt, v0, Cursor or Replit, then review the changes before deploying.
Add a Content-Security-Policy to my app. List every external domain the app loads scripts, styles, images, fonts and API calls from, then write a CSP that allows only those (include my Supabase project URL and wss:// for realtime in connect-src, and frame-ancestors 'none'). Ship it first as Content-Security-Policy-Report-Only, and tell me how to switch to enforcing.FAQ
Will a CSP break my app?
It can, if it blocks a domain your app needs. That's why you start with the Report-Only header, fix the violations you see in the console, and only then enforce it.
References
- MDN: Content Security Policy
- Next.js guide: Content Security Policy
- Vercel docs: custom headers
- Next.js docs: headers()
- Netlify docs: custom headers