Is my Bolt.new app secure? A security checklist before you publish
By Pritesh Ghodge, security engineer · Last updated 3 November 2026
Check your published Bolt app from the outside first.
Abbi Labs looks at your live site the way a stranger would: secret keys in the JavaScript, Supabase tables readable with your public key, exposed .env and .git files, and security headers. No sign-up for the quick check.
No sign-up. Read-only GET requests to what your site already serves publicly. Scan only sites you own or are allowed to test.
Weekly AI-app security checklist
One short email a week: a practical check for apps built with Supabase, Next.js and AI tools (RLS, leaked keys, headers and more). Unsubscribe anytime.
Bolt gets you from a prompt to a published app very quickly, and it has real security tooling built in. What it can't know is what your data is supposed to be: which tables are public, which belong to one user, which keys can spend your money. That's where most problems in AI-built apps come from. Here is the checklist I'd run on a Bolt app before sharing it with real users.
1. Run Bolt's own checks, and read what they say
According to Bolt's security docs there are two:
- Project security audit (paid plans): Publish → Run security audit. It reviews your code and database for who can see and change data, what your app reveals publicly, sign-in and sessions, ways the app can be misused (like changing a price), unsafe input, and keys in your code. It fixes most problems itself and lists anything that needs your action. Using the button doesn't use tokens; asking for an audit in the chat does.
- Database security check (all plans): click the database icon, then Security. Bolt says it uses the same checks as Supabase's Security Advisor, with Error, Warning and Info levels and an Ask Bolt to fix button.
Run them before you publish and again after big changes. Read the "needs your action" list, because those are the items Bolt couldn't fix for you, such as settings in your email or payment provider.
2. Don't wave through "RLS Policy Always True"
This is the warning I'd look at hardest. It means a policy has no condition, so it lets everyone it applies to through. Bolt's database security docs are candid: if your site has no sign-in, Bolt might write policies that let any visitor view, add, change and delete data. For each table, decide which of three cases it is:
- Public to read (menu, blog posts, portfolio): a select policy for everyone, and no insert, update or delete policy for visitors.
- Visitors can submit (contact form, waitlist, reviews): an insert policy only. Visitors shouldn't be able to read what other people submitted.
- Private (orders, messages, profiles, bookings): needs sign-in and a policy tied to the user.
A prompt you can paste into Bolt:
List every RLS policy in my database as a table: table, command
(select/insert/update/delete), role, and the exact USING and WITH CHECK
conditions. Then make visitors read-only on public tables, insert-only
on the contact/waitlist tables, and remove any visitor update or
delete policies. Show me the SQL before applying it.3. "Signed in" is not the same as "their own row"
Adding sign-in fixes nothing on its own. A policy like to authenticated using (true), or using (auth.uid() is not null), means every account can read every row, and anyone can create an account. The second form isn't "always true" to a linter, so it may not be flagged at all. Private tables need the row tied to the user:
create policy "Users read their own orders"
on public.orders for select to authenticated
using ((select auth.uid()) = user_id);
create policy "Users add their own orders"
on public.orders for insert to authenticated
with check ((select auth.uid()) = user_id);Watch the insert and update side too: with check (true) lets a user write rows with someone else's user_id. The free Supabase RLS policy checker flags RLS that's off, using (true), open insert/update and policies that never mention auth.uid(), from one read-only SQL query, analysed in your browser.
4. Secrets live in Secrets, never in a VITE_ variable
Most Bolt projects are Vite apps. Anything in a VITE_ variable is built into the JavaScript every visitor downloads. That's fine for your Supabase URL, the publishable/anon key and a Stripe publishable key. It is not fine for:
- the Supabase
service_roleorsb_secret_key (it bypasses RLS completely), - Stripe secret keys and webhook signing secrets,
- OpenAI, Anthropic, Resend or any other API key that costs money or sends mail as you.
Those go in Bolt's Secrets settings (database icon → Secrets), which Bolt describes as available to server functions without ending up in users' browsers. If a key was ever in the browser bundle, rotate it at the provider. Removing it from the code doesn't un-leak it.
Quick check on your published site: open DevTools → Sources (or view the JS files) and search for sk_live, sk-, sb_secret_ and service_role.
5. Server functions: moving a key there isn't the whole fix
When Bolt moves an OpenAI or Stripe call into a server (edge) function, the key is hidden, but the function's URL is still public. If it doesn't check who is calling, anyone can use it to spend your credits or do whatever the function does. For each function, ask:
- Does it require a signed-in user and verify the token, or is it deliberately public?
- Does it check the user is allowed to act on the record they passed in (not just that they're signed in)?
- Does it calculate prices on the server instead of trusting an amount from the browser?
- For payment webhooks: does it verify the provider's signature?
- Is there a limit on how often one user can call it, if each call costs you money?
More detail in AI API key exposed in your frontend.
6. Storage: private files in private buckets
If users upload anything (avatars are fine public; ID documents, invoices and attachments are not), check the bucket. A public bucket serves any file to anyone with its URL. Private buckets plus signed URLs and storage.objects policies scoped to the user's folder are the fix. Step by step: Is your Supabase storage bucket public?
7. Nothing extra is published with your site
From a browser, try /.env, /.git/HEAD and a .map next to one of your JS files on your published URL. You want a 404 or your app's normal page, not a file. Vite doesn't emit source maps for production builds unless build.sourcemap is turned on, so check that setting if you or the AI changed it. See exposed .env, .git and source maps.
8. Security headers on your host
A Content-Security-Policy, HSTS and clickjacking protection (X-Frame-Options or CSP frame-ancestors) are set by wherever your app is hosted, not by Bolt's editor. Check what your published site sends with curl -sI https://your-app.example and add the missing ones in your host's headers config. Examples: security headers for vibe-coded apps.
9. The two-account test
No checklist beats this. Sign up as user A and create some data. Sign up as user B in a private window. As B, try to open A's pages by changing IDs in the URL, and watch the network tab for requests that return A's rows. Then sign out and try again as a visitor, with the public key:
curl -s "https://YOUR-PROJECT.supabase.co/rest/v1/orders?select=*&limit=1" \
-H "apikey: YOUR_PUBLIC_KEY" \
-H "Authorization: Bearer YOUR_PUBLIC_KEY"[] or a permission error is what you want for private tables. Only test projects you own.
What an outside scan adds, and what it can't do
Bolt's audit reads your project from the inside. An outside scan checks what the published site actually serves to a stranger: the built JavaScript, the files on the host, the headers, and what your public key can read. It can't see your business rules or test as a signed-in user, so it doesn't replace the audit or the two-account test. Using both catches different mistakes.
Keep it that way
Every prompt can change a policy or add a variable, including an AI "fix" for an error. Abbi Labs scans your live app for leaked keys, Supabase tables readable with your public key, exposed .env/.git files and security headers. Monitor re-scans weekly and after deploys, and emails you only when something new appears.
FAQ
Does Bolt check my app's security?
Yes, in two ways, per Bolt's support docs. The project security audit (Publish → Run security audit, paid plans) reviews your code and database, fixes what it can and lists anything you need to do yourself; it doesn't use tokens and you can run it up to 30 times a day. The database Security tab (database icon → Security, all plans) uses the same checks as Supabase's Security Advisor and flags things like missing RLS or an 'RLS Policy Always True' policy.
What does the 'RLS Policy Always True' warning mean in Bolt?
A policy on one of your tables has no condition limiting who it applies to, so every visitor (or every signed-in user, depending on the role) gets that access. Bolt's docs say it may write such policies when your site has no sign-in, and that the warning is only acceptable if you're comfortable with every visitor being able to do what the policy allows, including changing or deleting data if the policy covers those.
Is it safe that my Supabase key is visible in my Bolt app?
The publishable (anon) key is designed to be public, as long as RLS is on for every table and each policy only allows what you intend. Secret keys (service_role or sb_secret_, Stripe secret keys, OpenAI and other API keys) must never be in browser code or in a VITE_ variable. Bolt's Secrets settings are where those go, for server functions to read.
If I add sign-in, is my data private?
Only if the policies then check whose row it is. A policy that allows any signed-in user lets every account read every row, and on most apps anyone can create an account. Private tables need a condition like (select auth.uid()) = user_id.
Does Abbi Labs work with Bolt apps?
Yes. Paste your published URL. The free quick check needs no sign-up and looks at your home page headers, its JavaScript for secret keys, /.env and /.git, and whether Supabase tables your code queries (plus common names) return rows with your public key. Full scans on a domain you've verified you own add storage buckets and source maps. It's an outside check, so it complements Bolt's audit rather than replacing it.
Related guides
- Lovable app security checklist (from a security engineer)
- How to check if your Supabase tables are readable by anyone
- Free tool: Supabase RLS policy checker
- NEXT_PUBLIC_ and VITE_ variables are shipped to every visitor
- Supabase service_role key exposed? Do this in the next 15 minutes
- Supabase "Security Definer View" warning: why your view bypasses RLS