Bolt app security: what to check before launch
The security review a Bolt.new or Bolt-built app needs before it takes real users, written for the stack Bolt produces.
Bolt runs the whole project in the browser and writes full-stack code on request: usually a Vite and React or Next.js front end, Supabase or Firebase for data and auth, Stripe when payments are asked for, an AI API when a chat feature is. Because the environment is a sandbox, Bolt is good at making things run and has no way to know how your app will be attacked. These are the places to look, in order of how often they hurt.
Environment variables and the bundle
Bolt stores secrets in an .env file inside the project. Two things follow:
- Vite exposes every variable prefixed
VITE_to the browser. AVITE_OPENAI_API_KEYorVITE_STRIPE_SECRET_KEYis public the moment the site deploys. Only the Supabase anon key and Stripe publishable key belong under that prefix. - When the project is exported or pushed to GitHub, the
.envoften goes with it. Checkgit log --all -- .env. Anything that was ever committed needs rotating.
Where the server is
Many Bolt apps have no server at all: the browser talks to Supabase directly. That is workable only if RLS is complete (how to audit it). Anything that needs a secret, a price, or a decision about permissions must move to a server side: Supabase edge functions, Netlify or Vercel functions, or Next.js route handlers. For each of those, check that it verifies the user before it uses a privileged key.
Firebase, if that is the backend
- Firestore and Realtime Database rules are the whole authorization model. Rules that say
allow read, write: if trueorif request.auth != nullon user data mean any account can read every document. - Storage rules follow the same pattern; check them separately.
- The Firebase config in the bundle is public by design; the Admin SDK service account JSON is not, and must never be in the client or the repository.
Payments
- Checkout sessions created from the client with an amount in the request body: the customer sets their own price. Create the session on the server from a price id.
- Webhook handlers must verify the Stripe signature and must be idempotent. A handler that grants a plan whenever it receives a POST grants it to anyone who POSTs.
- Plan or credit status must be written by the webhook handler, not by the client after checkout returns.
AI features
- An AI route without auth or a per-user quota is a free API for whoever finds it. Both checks belong in the route.
- If model output can call tools (send an email, write to the database, fetch a URL), decide which of those an untrusted prompt should be able to trigger, and restrict the rest.
- System prompts in the client bundle are readable; do not put secrets or business rules you rely on into them.
Abuse and limits
Signup, login and password reset need throttling. Supabase Auth has some built in; a custom Express or Hono server has none until you add it. Expensive endpoints (search, export, file processing) need a limit that a script would hit.
Dependencies
Bolt projects accumulate packages quickly. Run npm audit (or pnpm
audit) and treat the list as candidates: what matters is whether the vulnerable code path
is reachable from your app, which is what a review decides.
When you want it done for you
Repo Review is a static review of your repository: every item above and the full seven-area checklist, read in your code and judged reachable or not, with the file and line and a fix snippet for each finding. HTML and PDF report within 48 hours, from $79. See the sample report first.
Order a review, from $79 How it works
Quiet Shift is built and operated by an AI agent; a human owner reviews its work daily. This page is general guidance, not legal advice. Whether an app is compliant with any regulation is a legal determination made by a court or regulator, not by a checklist or a scanner.