BOLT.NEW SECURITY CHECKLIST
Bolt.new builds full-stack apps inside an in-browser WebContainer and then deploys to whatever provider you pick. Two things make Bolt apps especially fragile: the WebContainer environment treats .env as a literal text file (visible to anyone with the project URL), and Bolt’s scaffolds are tuned for “make it work in 30 seconds” — which means wildcard CORS, unauthenticated routes, and tokens stored in localStorage. The checklist below is the order we audit a typical Bolt app.
Treat Critical as launch-blocking. High is week-one. Medium is the cleanup you do once you have users.
How to use this checklist
Walk it once in the Bolt project view, ticking items as you go. After each fix, prompt Bolt to “regenerate” something unrelated and re-check — Bolt will sometimes silently revert a fix when it touches an adjacent file. After the whole list passes, run a black-box scan against the deployed URL (StackBlitz, Netlify, Vercel — wherever it landed) to confirm nothing regressed.
Critical (fix before launch)
1. Strip secrets from .env and the WebContainer
Why it matters. .env files in Bolt projects are part of the project tree. If the project is public — or if anyone has the share link — every value in there is readable, including database URLs, API secrets, and webhook signing keys. Bolt also pastes secrets into the chat history, which gets retained.
How to check. Open the project file tree, click .env and .env.local, and read every line. If anything starts with sk_, rk_, sk-proj-, re_, eyJ (JWT), or contains password, secret, or key, treat it as compromised. Search the chat panel for the same prefixes.
How to fix. Move secrets to the deploy target’s environment variable system (Netlify env, Vercel env, Fly secrets). In the WebContainer, replace real values with placeholders. Rotate anything that ever sat in .env in a public Bolt project.
2. Replace localStorage auth tokens with httpOnly cookies
Why it matters. Bolt scaffolds auth flows that store JWTs in localStorage because it’s the shortest path to a working demo. Any XSS — including from a vulnerable npm package or a misconfigured CSP — exfiltrates the token. Tokens in cookies marked HttpOnly; Secure; SameSite=Lax cannot be read by JavaScript.
How to check. Open DevTools → Application → Local Storage on the deployed app. If you see token, access_token, supabase.auth.token, or anything resembling a JWT, you are vulnerable.
How to fix. Move the auth callback to a server route (Netlify Function, Vercel Edge, or your backend) that sets the token as an httpOnly cookie. The frontend sees no token at all; the cookie travels automatically.
3. Replace wildcard CORS with an allowlist
Why it matters. The Bolt scaffolds for Express, Hono, and Fastify routes ship with cors() (no arguments), which is Access-Control-Allow-Origin: *. With credentialed requests, browsers will block this — but Bolt’s scaffolds also tend to set credentials: false, meaning your API will happily accept cross-origin reads from any site.
How to check. Hit one of your API routes from a browser console on a different origin: fetch('https://your-api/users').then(r => r.json()).then(console.log). If you get data, your CORS is too open.
How to fix. Replace cors() with cors({ origin: ['https://your-app.com'], credentials: true }). List every domain your frontend will run on; reject everything else.
4. Enable RLS or row-scoping on the database
Why it matters. Bolt apps usually wire up Supabase, Firebase, or a hosted Postgres. The scaffolded code talks to the database as if every authenticated user is allowed to see every row — because that’s what makes the demo work. Without RLS (Supabase/Postgres) or security rules (Firebase), one logged-in user can read everyone’s data.
How to check. In Supabase, run select tablename from pg_tables where schemaname = 'public' and rowsecurity = false. In Firebase, open Firestore → Rules and check whether any rule reads allow read, write: if true or if request.auth != null (the latter still grants every signed-in user full access).
How to fix. Add per-table policies scoped by auth.uid() = user_id (Supabase) or request.auth.uid == resource.data.userId (Firebase). Test by signing in as user A and trying to read user B’s data — it should 401, not return the row.
5. Sanitize LLM-rendered markdown and HTML
Why it matters. A lot of Bolt projects render LLM output to the user (chat apps, summarizers, code explainers). Bolt’s default markdown renderer often allows raw HTML, which lets an attacker who can influence the prompt — for example, by submitting a malicious document — inject <script> or <img onerror=> into your page.
How to check. Send a prompt that produces <script>alert(1)</script> or <img src=x onerror=alert(1)> and confirm it does not execute on render.
How to fix. Use react-markdown with the rehype-sanitize plugin, or render to plain text. Never feed LLM output through dangerouslySetInnerHTML without sanitization.
6. Verify auth-required routes actually require auth
Why it matters. Bolt-generated route guards usually live on the frontend (if (!user) return <Navigate to="/login" />), which is decoration, not security. Every backend route that returns sensitive data must check the JWT or session cookie itself.
How to check. For every API route, run curl https://your-api/route-name with no auth header. It should return 401, not 200 with data.
How to fix. Add a middleware that verifies the JWT/cookie before any handler runs. Reject unauthenticated requests at the route level, not the page level.
High (fix in the first week)
7. Pin OAuth and email-link redirect URLs
In your auth provider (Supabase, Auth0, Clerk, Firebase), the redirect URL allowlist must contain only your real production domain. Bolt’s “go fast” defaults often leave wildcards or localhost in the list, which lets an attacker complete an OAuth flow on a domain they control.
8. Add rate limiting to public endpoints
Bolt scaffolds do not include rate limiting. Add express-rate-limit, Hono’s rate-limiter, or your hosting platform’s built-in throttle on every public route — especially auth, password reset, and any LLM-calling endpoint (where each request costs you real money).
9. Validate inputs server-side, not just client-side
Generated forms validate with Zod or a hand-rolled schema in the React component, then trust the body on the server. Move validation into the route handler. The client check is for UX; the server check is the only one that matters.
10. Pin npm dependency versions
Bolt installs whatever the latest package resolves to during the WebContainer session. After deploy, that resolves differently. Pin every dependency in package.json (no ^, no ~) and commit the lockfile so production builds match what you tested.
11. Verify webhook handlers check signatures
Stripe, Resend, GitHub, and Supabase webhooks all sign their payloads. Bolt’s first-pass webhook handler usually skips the signature check. Without it, anyone who knows the URL can post fake “payment succeeded” events.
12. Disable email enumeration
Auth provider settings should return identical responses for “user exists” and “user does not exist” on signup, password reset, and magic link flows. Without this, attackers can enumerate which emails have accounts.
Medium (fix when you can)
13. Set security headers on the hosting layer
Add CSP, HSTS, X-Frame-Options, and X-Content-Type-Options at the Netlify/Vercel/Fly layer. Bolt’s HTML shell ships with no headers configured. CSP is the one that pays back the most against XSS.
14. Remove debug routes and seed scripts from the production build
Bolt scaffolds often include /dev, /debug, /seed, or /admin routes that dump data or reset the database. Add them to your build’s exclusion list or delete them outright before deploy.
15. Audit generated code for hardcoded admin credentials
Bolt sometimes inlines an admin password as a string literal “for testing”. Search the codebase for patterns like === 'admin', === 'password', or hardcoded JWT secrets ('supersecret', 'changeme').
16. Restrict file upload types and sizes
Generated upload handlers usually accept any MIME type at any size. Cap by file size, validate MIME against an allowlist, and store uploads in a non-executable bucket path.
17. Audit installed packages for known vulnerabilities
Run npm audit --production after every Bolt session. Bolt prefers the newest packages, which sometimes means a brand-new release with known issues nobody has filed yet.
18. Set up audit logging on auth events
Whatever auth provider you wired up, ship its audit logs somewhere you can query. You want a record of failed logins, password resets, and role changes long after the provider’s default retention.
After every Bolt regeneration
Bolt rewrites code on every prompt. Before pushing:
- Re-check
.envfor newly added secrets. - Search the diff for
cors(),localStorage.setItem, anddangerouslySetInnerHTML. - Re-test every privileged route with no auth header.
- Confirm the lockfile didn’t change unexpectedly.
- Re-run RLS / security-rules audit if the database schema touched.
Common attack patterns we see in Bolt apps
The shared share link. Developer shares the Bolt project URL with a teammate. Project is public by default; .env contains the production Supabase service key. The link gets indexed.
The wildcard CORS data dump. Attacker writes a one-line fetch() from their site, scrapes the entire users endpoint, posts the dump to a paste site. Nothing in your logs looks weird because the requests are well-formed.
The localStorage XSS. A vulnerable markdown renderer in the chat UI executes <img onerror>, which reads localStorage.getItem('access_token') and POSTs it to an attacker server. Now they have a session.
The unsigned webhook. Bolt-generated /webhook/stripe handler reads event.type === 'payment_intent.succeeded' from the body and credits the user — without verifying the signature. Attacker posts a fake event with a chosen customer_email.
Related Resources
How to Secure Bolt.new
Step-by-step security guide for Bolt apps — covers WebContainer hardening, CORS lockdown, and the auth migration patterns above in long form.
Is Bolt.new Safe?
In-depth security analysis of the platform itself — what Bolt does well, where the defaults bite, and what we find when we scan the typical Bolt app on the day it launches.
Automate Your Checklist
A checklist tells you what to look for. A scanner tells you what’s actually broken in the deployed app right now. VibeEval drives a real browser through your Bolt deployment, attempts the wildcard-CORS exfiltration and unsigned-webhook attacks above, and reports what got through — with the exact route or config to fix.
SCAN YOUR BOLT APP
14-day trial. No card. Results in under 60 seconds.