HomeIs my Bolt app secure?
Bolt.new security

Is my Bolt.new app secure? The flaws that show up again and again

Last updated: July 26, 2026

A Bolt.new app is often not secure by default. The most common flaws are a missing Row Level Security policy on Supabase tables, the Supabase key exposed in the browser bundle, and auth checks that run only on the client. None are exotic, and all are fixable once you can see them in your code.

Why do Bolt.new apps tend to have the same security gaps?

Bolt.new tends to produce the same gaps because it optimises for a working demo, not a hardened production app. The AI wires up a Supabase database and a front end that talks to it, and it prioritises "the feature works" over "the data is locked down." That is a reasonable default for prototyping, but it leaves specific holes you have to close before real users touch it.

The good news: because the pattern is so consistent, it is also predictable. The same three or four issues appear in most Bolt + Supabase apps, and each has a known, well-documented fix. The hard part for a non-technical founder is simply seeing which ones apply to your code. That is exactly what Explain My Build does: it reads your actual source and points at the specific lines, in plain English.

Honest scope

Explain My Build reads your code and flags patterns it can see there. It is not a live penetration test and it does not attack your running app. It also flags or refuses anything it cannot verify from the source. For a genuinely security-critical app (payments, health data, anything regulated), get a human security review on top of this. See our limitations page for the full boundary.

Flaw 1: Missing Row Level Security on your Supabase tables

The single most common Bolt flaw is a Supabase table with no Row Level Security (RLS) policy. When Bolt creates a table, it runs a CREATE TABLE statement but frequently does not enable RLS or write any access rules. With RLS off, the public anon key that ships in your front end can read or write every row in the table, not just the current user's rows.

In practice that means someone who opens your app's JavaScript, copies the Supabase URL and anon key, and queries the REST API directly can dump your whole table without ever logging in. This is not theoretical: security researchers have found real vibe-coded apps leaking names, emails, and payment details this exact way, the same class of flaw catalogued as CVE-2025-48757 for Lovable-generated Supabase apps.

What Explain My Build shows you looks like this, cited to your migration file:

create table profiles (
  id uuid references auth.users,
  email text,
  stripe_customer_id text
);
-- No "alter table profiles enable row level security;"
-- No policies. The anon key can read every row.

The fix: enable RLS on the table and add a policy so a user can only see their own rows. Explain My Build hands your AI a fix-list prompt like: "Enable Row Level Security on the profiles table and add a policy: authenticated users may select/update only rows where id = auth.uid(). Show me the SQL migration."

Flaw 2: The wrong Supabase key (or a key) in the browser

Supabase gives you two kinds of key, and mixing them up is a classic Bolt problem. The anon key is meant to be public and is safe in the browser only if RLS is on. The service_role key bypasses RLS entirely and must never leave your server. If Bolt (or a copy-paste) put a service_role key in client code, anyone can read and write everything, RLS or not.

Even the anon key deserves a second look: it is only "safe to be public" when your row-level rules are actually protecting the data behind it. Explain My Build reads your bundle and config and tells you which key is where, and whether the key that is exposed is one that should be.

The fix: keep the service_role key server-side only (in an environment variable your front end can't read), rotate it if it ever shipped to the client, and confirm the anon key is backed by RLS. Our API key glossary entry explains the distinction in plain terms.

Flaw 3: Auth checks that only run in the browser

A third recurring Bolt flaw is authentication that only runs on the client. The generated code hides a button or a page unless you're "logged in," which looks secure. But that check happens in JavaScript the user controls, so an attacker can call your API or database directly and skip it entirely.

The rule from the security community is blunt: never trust client-side auth state. Every sensitive action needs to be verified on the server (or enforced by an RLS policy in the database). Explain My Build flags spots where a check exists only in the front end with no server-side counterpart, and cites the file.

The fix: move the real check server-side, or enforce it in the database with RLS. A hidden button is a UI nicety; the server or the database is where security actually lives.

What Explain My Build gives you for a Bolt app

Paste your repo (or run it locally so code never leaves your machine) and you get three things, each cited to real lines in your code:

  • A plain-English explanation of each security gap: what it is, where it lives, and why it matters, written for a non-technical founder.
  • A ranked, code-verified fix-list you can hand straight to your AI (Cursor, Claude Code, Bolt itself) to make the change.
  • A founder runbook so you understand how the app is wired, not just what to patch.

The runbook and fix-list are free. If you also want the shareable end-user guide for the people who use your app, that's the $19/month tier (or $12/month founding for the first 100). See pricing. And when you're ready to build the fixes, walk through documenting your Bolt app first so you know exactly what you're changing.

Frequently asked questions

Is my Bolt.new app secure by default?

Usually not, without changes. Bolt.new builds a working app quickly and commonly ships with missing Row Level Security on Supabase tables, the Supabase key visible in the browser, and auth checks that run only on the client. Each is a known, fixable issue, the challenge is spotting which ones apply to your specific code.

Can someone steal data from my Bolt Supabase app?

Yes, if Row Level Security is off. The public anon key ships in your app's JavaScript, so anyone can copy it and query your Supabase database directly. Without RLS policies, that query returns every row, not just the logged-in user's. Turning on RLS with per-user policies closes this. Explain My Build tells you whether your tables are protected.

What is the difference between the Supabase anon key and service_role key?

The anon key is public and safe in the browser only when Row Level Security protects the data behind it. The service_role key bypasses all security rules and must stay server-side. If a service_role key ends up in client code, anyone can read and write everything. See our API key glossary entry.

Does Explain My Build actually hack my app to test it?

No. Explain My Build reads your source code and flags security patterns it can see there, then explains them and generates a fix-list. It is not a live penetration test and never attacks your running app. For a genuinely security-critical app, pair this code review with a human security audit. See limitations.

How do I fix missing RLS in my Bolt app?

Enable Row Level Security on each Supabase table and add a policy so users can only see their own rows (typically id = auth.uid()). Explain My Build generates the exact prompt to hand your AI, cited to your table. Walk through documenting your Bolt app to see every table that needs it.

Turn your app into a guide your users can follow.

Paste a public GitHub link and get your founder runbook + fix-list free in about a minute — no sign-up. Private code runs entirely in your browser.

Explain my build — free →