Skip to content

Is your Bolt app safe?

Is Bolt safe to build on? The code is rarely the problem. What decides it is whether the database tables Bolt wrote for you were ever locked.

Vlad Tkachenko5 min read
Reeve's security-check card for Bolt apps, with the Bolt logo on a white tile.

Logos are the property of their respective owners, shown to indicate compatibility.

In short

  • A Bolt app is usually safe on the code side. What decides it is whether the database tables Bolt generated were ever locked.
  • Tables created by running SQL do not get Row Level Security by default, and writing SQL is how Bolt creates them.
  • A publishable key in your app is correct. sb_secret_… or service_role reaching the browser is the one to rotate today.

Bolt writes the whole project: the screens, the wiring, and the database tables underneath. That last part is the one you never see, and it is where almost every "my Bolt app is leaking data" story actually starts.

Here is the part that guide after guide gets wrong: the code Bolt wrote is rarely the problem. The problem is usually a single per-table switch in your database that was never turned on, because of how the tables were created rather than because anyone made a mistake.

What Bolt hands to a visitor, and what it keeps

Two halves, and only one of them is private.

Think of it as a shop. Bolt builds you a shopfront (pages, buttons, forms), and the whole shopfront is handed to every visitor who loads your site. It has to be. A browser cannot display a page it was not given, so there is no version of this where the front of your app is secret. Behind it sits a stockroom, your Supabase database, which is a separate building with its own lock.

The assumption that costs people is that the shopfront controls the stockroom. It does not. Your database sits on the internet with its own address, and that address is printed on the shopfront because that is how your own app reaches it. Anyone who reads your published files can read the address too, and then talk to the stockroom without ever walking through your shop.

Is it a problem that my Bolt app has an API key in it?

Usually not. It depends entirely on which key, and there are two that look almost identical.

Both are called API keys. Only one of them was ever meant to be readable.

A publishable key names your project and nothing else. Supabase calls it sb_publishable_… in new projects and anon in older ones, and it is built to sit in a browser where anyone can read it. A secret key (sb_secret_…, or service_role before the rename) is the opposite. It ignores every rule you have written and reads and writes every row in every table.

They sit beside each other in the Supabase dashboard, run to a similar length, and behave identically while you are building. Nothing breaks if the wrong one gets copied, which is precisely why it survives to production. The longer version of how to tell them apart takes about a minute to read.

The switch that decides who your database answers

Row Level Security is a per-table setting in Supabase that decides, row by row, who may read what. Off, and your publishable key returns the entire table. On, with a policy written, it returns only the rows that policy permits.

Your app and a stranger knock on the same door. The setting decides who gets in, not your app's screens.

Now the part that applies to a Bolt project specifically. Supabase enables Row Level Security by default for tables created in the dashboard's Table Editor, the point-and-click one. Tables created by running SQL do not get it, and have to be enabled deliberately.

Bolt creates your tables by writing SQL.

So the usual shape of a Bolt project is a set of generated tables that arrived unlocked, sitting next to anything you later added by hand, which did not. The two are indistinguishable in the editor and both work perfectly. And enabling the setting is not the finish line either: a table with Row Level Security on and a policy that permits everyone is open while reporting itself as closed.

How to check your own Bolt app in about ten minutes

Read your policy list. In Supabase, Authentication → Policies shows every table with whether Row Level Security is on. Start with anything marked disabled; those are readable by anyone with your project address.

Confirm which key you shipped. Settings → API in Supabase shows both. The publishable one in your app is correct and needs nothing. If a secret key was ever pasted into the project, rotate it there before touching your code: deleting the line does not close the door, because the old value survives in anyone's cached copy of your site.

Check your storage buckets. A bucket marked public can be listed and downloaded by anyone, whether or not your app ever links to the files in it.

Then look from outside. Everything above tells you what is configured. It does not tell you what a stranger can actually reach, which is a different question and the one that matters. Our free scan reads your live site the way any visitor would and gives you a grade in about 20 seconds, no account required: scan your app.

What to do

  • Everything Bolt ships to a browser is readable by anyone. That is how browsers work, and hiding it is not an option worth pursuing.
  • A publishable key in your app is correct. A secret key (sb_secret_… or service_role) is the one to rotate today.
  • Tables created by running SQL do not get Row Level Security by default, and writing SQL is how Bolt creates tables.
  • Turning the setting on is step one. A policy that allows everyone leaves the table open while the dashboard shows it as protected.
  • Your app working is not evidence that it is locked. Both states look identical from the inside.

Open Authentication → Policies in Supabase and read the list top to bottom. If anything there says Row Level Security is disabled, that table is where to start, and the 10-minute security checklist covers the rest of the surface once you have.

What can actually go wrong with a Bolt app

None of these mean you did anything wrong. They come with building fast. Here's what's worth checking:

  • A secret key ending up in the browser (the VITE_ trap)

    Bolt apps are usually built with Vite, which has one rule that catches people out: any setting whose name starts with VITE_ gets baked into the code that runs in your visitor's browser, where anyone can read it. Name a real secret VITE_SOMETHING and it ships to the public. Some keys are meant to be public (like a Supabase "anon" key), which is fine: Reeve tells the safe ones from the dangerous ones, so no false alarms.

  • Your database left open (Supabase RLS off)

    Bolt often wires your app to Supabase for data. Supabase has a switch called Row Level Security (RLS) that decides who can read or change each row. If it's off, your tables can be readable, or editable, by anyone who finds the address. It's the most common serious issue in AI-built apps, and it's invisible unless you check.

  • An exposed .env or config file

    The .env file holds a project's keys and passwords. Sometimes it gets published alongside the deployed app by accident. If it's reachable from the outside, it's a shortcut to everything sensitive. Reeve checks whether yours is quietly accessible.

  • Public file storage

    If people upload files to your app, those live in storage "buckets." A bucket left public means anyone can list or download what's inside, so a private upload can end up visible to everyone. Reeve checks whether your buckets are listable; it never downloads anyone's files.

  • Source maps left on

    A "source map" is a helper file that reveals your app's original code. Handy while building, but if it ships to production it hands strangers a readable map of how your app works, making every other door easier to find. Low urgency, but worth tidying.

  • Missing safety headers & open endpoints

    Small settings that tell browsers how to protect your visitors, plus whether your data endpoints answer to anyone or any website. Each one is minor on its own, but together they widen the gap. Reeve flags the ones that are missing.

What Reeve is, and what it isn't

Reeve is a free, read-only check from the outside, like an inspector walking the perimeter and trying the doors. It catches the common, high-impact mistakes fast. It is not a full security audit, and a clean grade isn't a guarantee; it means the obvious doors are shut.

Bolt and StackBlitz keep improving what gets generated, and if your app uses Supabase, Supabase's own advisor flags database problems inside its dashboard. Both help. What Reeve adds: you live in Bolt, not in a dashboard, and those tools speak developer. Reeve looks at your whole deployed app from the outside, the way a stranger would, and tells you what it finds in words you can act on. Or hand the watching to us and get back to building.

Want it handled, not just checked?

Reeve Care keeps watching your app, backs up your data, and helps you fix what breaks, so you can keep building instead of worrying.

Learn about Reeve Care

FAQ

Is my Bolt app secure by default?

Bolt gives you a working app fast, but "secure by default" depends on how it's wired, especially your environment variables and, if you use Supabase, your database rules. The only way to know is to check what's actually exposed, which Reeve does free in about 20 seconds.

Why did my API key leak in a Bolt app?

Usually because it was stored in a setting starting with VITE_. Vite inlines those into the browser bundle on purpose, so any secret named that way becomes public. Reeve reads your app's loaded code, finds keys, and tells you which are safe to expose and which need to move to the server.

Does Bolt use Supabase, and is that safe?

Bolt frequently connects apps to Supabase. Supabase is safe when Row Level Security is on and only your public "anon" key is in the frontend. If RLS is off or a "service_role" key leaked, your data can be exposed. Reeve checks both without ever reading your actual data.

Will scanning my Bolt app change anything?

No. Reeve only looks at what's already public from the outside. It never logs in, never changes anything, and never downloads your files. Read-only, like checking whether a door is locked without stepping inside.

Bolt wrote my database tables. Are they locked by default?

Often not, and the reason is mechanical. Supabase turns Row Level Security on automatically for tables you create by clicking around in the Table Editor, but not for tables created by running SQL. A builder creates tables by running SQL, so those tables arrive with the switch off unless something turned it on afterwards.

The preview worked and the deployed app works. Does that mean it is configured correctly?

No, because both would work either way. An app with no rules on its database behaves exactly like an app with correct rules, right up until someone queries the database directly instead of going through your screens. Working is not the same test as protected.

Where do I look to see whether my Bolt project has this problem?

Open your Supabase project and go to Authentication, then Policies. Every table in the public schema is listed with whether Row Level Security is enabled. Any table showing disabled can be read by anyone holding your project URL and publishable key, and both of those are inside the app you published.

Written by

Vlad Tkachenko

Founder, Reeve

I spend my time looking at apps built with Lovable, Bolt, v0, Cursor and Replit, and at the short list of mistakes that keep turning up in them.

More about the author

Built somewhere else? We've got the same honest rundown for:

← See all builder safety guides

Automated external check, not a full audit. Absence of findings is not a guarantee of safety.