Abbi Labs

Guides

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:

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:

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:

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:

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.

Run a free scan

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

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.