Bolt.new security: what Bolt checks for you, and where Bolt apps still leak

Bolt.new is a legitimate AI app builder from StackBlitz that handles part of your security: it keeps secrets in server functions, turns on row level security (RLS) for the tables it creates and, on paid plans, audits your project before you publish. Whether your app leaks still depends on your project: the RLS policies on each table, the keys in your frontend, and whether each server function checks who is calling.

The team behind Keybrum's attacksUpdated 15 min read

In short

  • Bolt Database is built on Supabase. The public key in your JavaScript is expected, and your RLS policies decide what a stranger can read, change or delete.
  • When your app has no sign-in, Bolt may write policies that let any visitor view, add, change and delete rows. The Security tab flags them as RLS Policy Always True: fine for a public menu, a leak for orders or messages.
  • Run the project security audit from the Publish menu before you publish (paid plans, no tokens used), and reopen the database Security tab after every schema change.
  • Secret keys belong on the Secrets page, where only server functions read them. Anything in a VITE_ or EXPO_PUBLIC_ variable ships to every visitor.
  • Both Bolt checks work from inside your project. Test the published app the way a stranger would too: signed out, then signed in as a second account.
On this page

Is Bolt.new safe? The short answer

Yes, Bolt.new is a real product and a reasonable place to build: it is the AI app builder made by StackBlitz, with built-in hosting, a built-in database and two security checks of its own. The platform keeps your secret keys out of the browser and turns RLS on for the tables it creates. What it cannot decide for you is who may read each row, which server function needs a signed-in user, and where you pasted a key. Those choices live in your project, and that is where apps built with Bolt leak.

The pattern is documented across AI builders. Escape's researchers analyzed more than 5,600 public apps built on vibe coding platforms and reported over 2,000 vulnerabilities, more than 400 exposed secrets and 175 instances of personal data. Most of their sample was Lovable, with Bolt.new among the smaller samples, so the numbers describe the pattern more than Bolt itself. On Lovable, which uses the same Supabase foundation, CVE-2025-48757 was assigned after a scan of 1,645 apps found 170 with missing or weak RLS, about one in ten.

What Bolt is responsible for, and what you are

AreaBolt handlesYou handle
HostingPublishes to a bolt.host address, or your own domain on a paid plan, and issues the HTTPS certificate for custom domainsChoosing a public or private site (private needs a paid plan), and what each page shows
DatabaseRuns it, turns RLS on for the tables Bolt creates, flags risky settings on the Security tabRLS on tables you add, and policies that limit each user to their own rows
SecretsStores them and reads them only inside server functions, never in your files or the published siteNever pasting a secret key into code, chat or a public variable, and rotating one that leaked
Sign-inEmail and Google sign-in; leaked password protection is on by default for Bolt databasesDeciding whether sign-ups stay open (on by default) and what a brand new account can read
PaymentsGenerates the Stripe checkout and webhook functions; its guide says webhook signatures are verified automaticallyConfirming the verification is still there after later prompts, and testing in Stripe test mode
Security checksA project security audit on paid plans and a database Security tab on all plansRunning them, doing the items marked as needing your action, and testing the live app
From Bolt's own documentation, November 2026. The right-hand column is the part no scanner can finish for you.

Bolt says as much itself. After an audit, it fixes most problems on its own, but some fixes are yours to make, such as a setting in a payment or email provider you connected, and Bolt lists them under a Needs your action heading in the chat.

The stack Bolt builds, and where it leaks

Bolt builds web apps in a JavaScript framework, which you can choose or leave to Bolt, and builds iOS and Android apps through its Expo integration. New projects use Bolt Database by default, on every plan. On Pro and Teams plans you can start with your own Supabase project instead, or later claim a Bolt database into your Supabase account. Bolt Database is built on Supabase: you can claim it into a Supabase account, its Security tab uses Supabase's Security Advisor checks, and Bolt describes its sign-in email templates as powered by Supabase technology. Sites publish to Bolt hosting by default; Netlify is an option for sites without a database or backend.

That stack has one consequence to keep in mind. Your frontend talks to the database directly, with a public key that every visitor's browser downloads. Bolt's own documentation puts it plainly: anyone who visits your site can send requests to your database directly, without using your site's screens. The Supabase anon key guide explains why that key is meant to be public. The policies behind it are the only gate.

WhereWhat a stranger can reachHow it leaks
Frontend bundleEvery value in a VITE_ variable, plus the table names your code queriesA secret key placed in a public variable or written straight into the code
TablesRows through the database API, with the public key from your JavaScriptRLS off on a table you added, or a policy whose condition is just true
Signed-in dataAnything a policy gives to every accountA policy that checks the user is signed in but never compares the row's owner to auth.uid(), while sign-ups are open
File storageEvery file in a public bucket, by its linkUploads such as invoices or ID scans stored in a bucket marked Public
Server functionsAny function your app callsAn AI or email function that answers callers without checking their session
Mobile appEvery EXPO_PUBLIC_ variable inside the app you shipA secret key in a public Expo variable, which anyone can extract from the installed app

What Bolt's security checks catch, and what they do not

Bolt has two checks, and they are worth using. The project security audit runs from Publish > Run security audit on paid plans. It reviews your code and database, fixes what it can, and neither the audit nor its fixes use tokens; prompting Bolt to audit in the chat does. The database Security tab is available on every plan and runs the same rules as Supabase's Security Advisor.

CheckWhat it looks atWorth knowing
Project security auditWho can see and change data, what public screens reveal, sign-in and sign-out, misuse such as changing a price or claiming a single-use item twice, visitor input, keys in code, which other sites may call your appPaid plans, up to 30 audits a day. The button switches to Security audit up to date until you change the project
Database Security tabRLS turned off, RLS Policy Always True, Function Search Path Mutable, leaked password protection turned offAll plans. It flags open policies even when public access is what you want, so read each one instead of ignoring the list

Credit where it is due: the audit looks for business logic flaws, like a user changing a price or skipping a required step, a kind of bug that a settings check like the Security tab cannot see. The limit is the vantage point. Both checks work from inside the project, reading your code, rules and settings. Bolt does not describe either one as sending requests to your published site the way a stranger would. They also see only what is in the project today, so a table you created by hand, a database you manage in Supabase, or a key that shipped in an earlier build can slip past them.

The holes that remain in Bolt apps

Open policies on apps without sign-in

Bolt's documentation warns that if you have not asked for sign-in, Bolt might write policies that allow any visitor to view, add, change and delete the data in your database. For a blog or a menu, reading is fine, but writing is not. For a contact form, visitors should be able to add rows, not read everyone else's messages. Bolt's guide suggests sorting each table into one of three cases: visitors only view, visitors only submit, or the data stays private behind sign-in.

Sign-in checked, ownership not

Once you add sign-in, the common mistake moves one step. A policy written for authenticated users that never compares a column to auth.uid() lets every account read every row. Sign-ups are on by default in Bolt, so a stranger only needs to create an account. This is an IDOR, and it is the access control bug we see most often in generated apps.

Secret keys in the frontend

Bolt's Secrets only work with server functions, which is the right design. Keys still leak when they are pasted into the code or into a public variable. Vite bundles every VITE_ variable into your source code at build time, and Expo inlines every EXPO_PUBLIC_ variable into the app; both projects tell you never to put secrets there. An OpenAI, Stripe secret or Supabase service role key in the bundle is an emergency: see API keys exposed in the frontend and the service role key guide.

Server functions that answer anyone

A server function keeps a key off the browser, but it does not decide who may use it. A function that calls an AI model with your key, sends email or changes data must check the caller's session itself. If it does not, anyone holding the public key from your JavaScript can call it in a loop, and you pay the bill. See unprotected AI endpoints.

Storage and payments

When Bolt sets up storage for user uploads, it aims for private buckets with RLS policies, and its docs still tell you to confirm each bucket's visibility yourself. A public bucket serves every file to anyone with the link. For payments, Bolt's Stripe guide says webhook signatures are verified automatically; that verification lives in a generated function, and a later prompt can rewrite it. Stripe webhook security shows what the check must look like.

How to check your Bolt app

Six checks, from the cheapest to the most telling. The first four happen inside Bolt and change nothing.

  1. 1

    Run the project security audit

    Click Publish, then Run security audit. Expand the summary to see what Bolt changed, and do every item under Needs your action. On a free plan, use the database Security tab instead.

  2. 2

    Read the database Security tab

    Click the database icon at the top of the project, then Security. For each RLS Policy Always True warning, ask yourself whether you are comfortable with every visitor changing or deleting that table.

  3. 3

    Query the catalog

    In the database settings, open Tables, pick any table and click Query. Replace the starting query with the SQL below and click Run Query. If you connected your own Supabase project, use its SQL editor instead. To review a policy line by line, paste it into the Supabase RLS checker.

  4. 4

    Search the code for secret keys

    Search the project files for sk_live_, sk-, service_role, sb_secret_ and PRIVATE KEY. Public variables should hold only the database address and the public key. Paste a long key starting with eyJ into the Supabase key checker to see its role, and use the API key leak checker for other formats.

  5. 5

    Use the published app as a stranger

    Open the live site in a private window, signed out, and try every page and form. Then sign up with two accounts, create a record with the first, and try to open it with the second, for example by changing an id in the address bar.

  6. 6

    Read one table from outside

    Run the request below against your own app, with the public key it already ships. It shows exactly what a stranger gets from one table.

sql
-- 1. Every table in public: is RLS on, and how many policies does it have?
select c.relname as table_name,
       c.relrowsecurity as rls_on,
       count(p.policyname) as policies
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
left join pg_policies p
  on p.schemaname = n.nspname and p.tablename = c.relname
where n.nspname = 'public'
  and c.relkind in ('r', 'p')
group by c.relname, c.relrowsecurity
order by rls_on, table_name;

-- 2. Policies with no condition at all
select tablename, policyname, cmd, roles
from pg_policies
where schemaname = 'public'
  and (qual = 'true' or with_check = 'true');

-- 3. Policies for signed-in users that never check the owner
select tablename, policyname, cmd
from pg_policies
where schemaname = 'public'
  and 'authenticated' = any (roles)
  and coalesce(qual, '') not like '%auth.uid()%'
  and coalesce(with_check, '') not like '%auth.uid()%';
Read-only queries on your own database. A table with rls_on false is open to the public key. Rows in the second and third results are leads: confirm each one against what the table holds.
bash
curl "https://YOUR_DATABASE_ADDRESS/rest/v1/orders?select=*&limit=1" \
  -H "apikey: YOUR_PUBLIC_KEY"
Your own app only. Copy the address and public key your Supabase client already uses. With a legacy key starting with eyJ, also send -H "Authorization: Bearer YOUR_PUBLIC_KEY". A row in the answer means anyone can read that table.

Fixes, with prompts for Bolt

Bolt fixes things best when you describe the rule you want, table by table. Paste a prompt, read what Bolt changed, then run the audit or the Security tab again. If a fix breaks something, version history can take you back, but going back also removes the security changes, so prefer a follow-up prompt.

Lock the open tables

text
Turn on row-level security for every table in my database. For each table, write policies that allow only what the app needs: posts can be read by anyone but changed by no visitor; contact_messages can be added by anyone but read by no visitor; orders, profiles and messages can be read and changed only by the signed-in user who owns the row (user_id = auth.uid()). Remove every policy whose condition is just true. Then list each table with its policies.

To check what Bolt wrote, compare it with the shape of a correct owner policy:

sql
-- Bad: every account reads every order
create policy "Signed-in users read orders"
on public.orders for select to authenticated
using (true);

-- Good: each user reads only their own orders
create policy "Owners read their orders"
on public.orders for select to authenticated
using ((select auth.uid()) = user_id);
The same pattern applies to update and delete, with a with check clause on insert and update. The Supabase RLS guide covers teams, public read with owner write, and views.

Move keys to Secrets

text
Find every API key, password or private key written in the project files or in a VITE_ or EXPO_PUBLIC_ variable. Move each one to a server function that reads it from Secrets, and change the frontend to call that function instead. Tell me the name of each secret I need to add.

Then rotate every key that was exposed, at the provider. Moving a key out of the code does not invalidate copies already downloaded from an earlier build.

Protect server functions

text
In every server function that calls an AI model, sends email, or reads or changes user data, reject requests without a valid signed-in user session and return 401. Check that the user owns the record they ask for. Add a per-user rate limit to the AI functions. In the Stripe webhook function, verify the Stripe-Signature header with the webhook signing secret before handling any event.

Make uploads private

text
Make every storage bucket that holds user uploads private. Add policies so each user can upload, read and delete only files in their own folder, and serve files through signed URLs instead of public links.

The Supabase storage guide shows the folder-per-user policy in SQL if you want to check the result.

The traps after the first fix

  • Tables you add yourself. Bolt turns RLS on for the tables it creates. A table you create in the Query editor, or in Supabase after claiming the database, needs it turned on by hand.
  • Claiming the database to Supabase. Leaked password protection is on by default in Bolt databases, but it turns off when you claim the database on a Supabase free plan. The Security tab then shows Leaked Password Protection Disabled.
  • Views and functions. A view can hand out a table that RLS protects, and a function marked security definer runs with its owner's rights. The Supabase RLS guide shows how to close both.
  • Rolling back. Restoring a version from before the audit also removes the fixes Bolt made, so run the audit again after any restore. If your project uses your own Supabase database, a restore changes the code but not the database, so the two can drift apart.
  • A private site is not a private database. Making the site private hides its pages. Test the database with the request above anyway, since the public key may already be in old copies of your JavaScript.
  • Missing headers. Check the response headers of your published site with the security headers checker, especially if you use a custom domain or Netlify.

Test the published app, not only the project

Bolt's audit reads your project. A stranger never sees your project: they see the published site and the JavaScript it sends. Testing from that side shows what actually answers, after every setting, rollback and manual change has been applied.

That is what Keybrum does, on apps whose owner proved ownership. It finds the database address and public key in your JavaScript, then tries to read, insert and update rows as a stranger and as a freshly signed-up account. It reads one account's records with a second account, lists and uploads to storage buckets, calls AI functions without an account, sends an unsigned Stripe event to your webhook, and looks for secret keys in the bundle and in readable rows. Every finding comes with the request that worked.

Bolt.new security checklist

  • The project security audit ran after your last change, and every item under Needs your action is done.
  • The database Security tab shows no RLS Policy Always True warning on a table that holds private or editable data.
  • Every table in public has RLS on, including the ones you created yourself.
  • No policy for signed-in users skips the owner check (auth.uid()).
  • Sign-ups are turned off if the app is meant for invited users only.
  • No secret key appears in the project files, a VITE_ variable or an EXPO_PUBLIC_ variable, and every key that ever did has been rotated.
  • Every server function that calls an AI model, sends email or changes data checks the session and rate-limits callers.
  • Buckets with user uploads are private, with per-user policies.
  • The Stripe webhook function verifies the Stripe-Signature header.
  • You tried the live app signed out, then with a second account, and saw only what you meant to show.

For the same audit on any AI-built app, see the vibe coding security checklist and the wider list of vibe coding security risks. Building on Lovable too? The Lovable security guide covers its scanners.

Questions

Is Bolt.new safe to use?

Yes, as a platform: it keeps secrets in server functions, turns RLS on for the tables it creates and offers a security audit and a database scan. Whether your app is safe to launch depends on your database policies, your keys and your server functions. Run Bolt's audit, then test the published app signed out and with a second account.

Is Bolt.new legit?

Yes. Bolt.new is the AI app builder made by StackBlitz, with paid plans and a public help center. Being a legitimate service says nothing about the app you build with it, which is why Bolt ships its own security checks.

Does Bolt.new use Supabase?

Bolt Database, the default for new projects, is built on Supabase: its Security tab uses Supabase's Security Advisor checks, and you can claim it into your own Supabase account. On Pro and Teams plans you can also start a project on Supabase or connect an existing Supabase project. Either way, RLS policies protect your data, as explained in the Supabase RLS guide.

Is the Bolt security audit free?

The project security audit is available on paid plans, and neither the audit nor its fixes use tokens when you start it from the Publish menu. Asking Bolt to audit in the chat uses tokens. The database Security tab is available on every plan.

Where should I put API keys in a Bolt app?

On the Secrets page of your database settings, so that only server functions read them. Bolt never writes a secret's value into your files or the published site. A key in a VITE_ or EXPO_PUBLIC_ variable ships to every visitor, so only the database address and the public key belong there.

How do I know if my Bolt app leaks data?

Run the queries in this guide from the Tables query editor, and read the database Security tab. For an outside view, paste your app's address into the free check: it shows the backend, exposed keys and the tables your JavaScript names in about ten seconds, without sending anything to your database.

Sources

  1. 1.Check your project's security, Bolt Help Center
  2. 2.Database security settings, Bolt Help Center
  3. 3.Secrets, Bolt Help Center
  4. 4.Add and manage a built-in database in your Bolt project, Bolt Help Center
  5. 5.Supabase for databases, Bolt Help Center
  6. 6.Database authentication settings, Bolt Help Center
  7. 7.Database file storage settings, Bolt Help Center
  8. 8.Database tables, Bolt Help Center
  9. 9.Stripe for payments, Bolt Help Center
  10. 10.Publish your project to a live website, Bolt Help Center
  11. 11.Netlify for hosting, Bolt Help Center
  12. 12.Glossary, Bolt Help Center
  13. 13.Env variables and modes, Vite
  14. 14.Environment variables in Expo, Expo Documentation
  15. 15.Methodology: How we discovered over 2k high-impact vulnerabilities in apps built with vibe coding platforms, Escape
  16. 16.CVE-2025-48757, NIST National Vulnerability Database
  17. 17.Statement on CVE-2025-48757, Matt Palmer

Your app is public. So are its mistakes.

Check what any attacker can already see in it, free, in ten seconds. The full attack, with proof and fixes: €49 once, or €29 a month on a plan.

or continue with Google or GitHub