← All posts
·5 min read·GuardLayer

Supabase security breaches: what actually happened

SupabaseRLSSecurityData Breach

Has Supabase been breached? No — the platform itself hasn't had a data breach. What keeps happening is that apps built on Supabase leak their users' data through misconfiguration: a table with Row Level Security turned off, or a service_role key exposed to the browser, either of which turns Supabase's auto-generated API into an open door for anyone holding the public anon key. Here are the documented incidents, the single pattern behind almost all of them, and how to check your own project in 60 seconds.

Has Supabase itself been hacked?

No. There's no known compromise of Supabase's infrastructure that exposed customer data. When people search "Supabase breach," what they're actually finding are application-level exposures — projects where the developer never enabled RLS, so every row was readable (and often writable) through the documented REST API using the anon key that ships in every browser bundle.

That distinction matters, because it also means the fix is entirely in your hands. Supabase gives you the lock; these incidents are cases where it was left unlocked.

The documented incidents

CVE-2025-48757 — the Lovable exposure (May 2025). The flagship case. Security researcher Matt Palmer analyzed a large sample of apps generated by the AI builder Lovable and found 303 endpoints across 170 projects with Supabase tables readable by anyone sending the public anon key — exposing emails, addresses, and in some cases API keys — because RLS was never enabled on the generated tables. It was assigned CVE-2025-48757 (CVSS 9.3 on the CVE record), though Lovable disputes the framing, arguing the misconfiguration is the developer's responsibility rather than a platform flaw. Either way, the data was reachable. We broke down the mechanics in the Lovable RLS vulnerability, explained.

Exposure at scale. The Lovable finding wasn't isolated. Multiple security researchers have since demonstrated that thousands of Supabase-backed apps are queryable with nothing more than a curl command and the public anon key, dumping entire tables of user data. At least one open-source Supabase leak-scanner was built after its author caught a live database exposing roughly 13,000 users. The common thread every time: RLS off, or a service-role key that shipped to the client.

Supabase's own response. Supabase has treated this as a real problem rather than blaming users. Its 2025 security retrospective documents the push toward safer defaults, and starting in 2026 new projects no longer expose public schema tables through the Data API by default — closing the exact gap that made "RLS off" instantly exploitable. Existing projects still need to be checked manually.

The one pattern behind almost all of it

Strip away the app names and it's the same mistake every time:

  • Every table in the public schema is reachable through Supabase's auto-generated PostgREST API.
  • That API accepts the anon key, which is public by design and lives in your client bundle.
  • The only thing standing between an anonymous request and your rows is Row Level Security.
  • RLS has historically been opt-in — a table created via SQL or the old Table Editor shipped with it off — and AI code generators happily produced create table statements with no policy attached.

So the "breach" is usually one missing line per table. No exploit, no zero-day — just the documented API doing exactly what it was told, against a table nobody locked. (This is also why disabling RLS to "fix" a blocked query is so dangerous: it re-opens the exact hole.)

Check your own project in 60 seconds

Before you assume you're fine, confirm it. First, ask Postgres which public tables currently have RLS off (run in the SQL editor):

select tablename
from pg_tables
where schemaname = 'public'
  and not rowsecurity;

Anything that query returns is reachable by anon right now — if you didn't intend that table to be public, it's exposed. Then scan your migrations for the statement that turns the lock off:

grep -rniE 'disable[[:space:]]+row[[:space:]]+level[[:space:]]+security' supabase/migrations

And make sure no service_role key ever reached the browser — see how a leaked service-role key exposes everything and whether the anon key is safe to ship (it is; the service-role key is not).

The fix for an exposed table is never to leave it open: enable RLS and add a policy that grants exactly the access you intended. The complete guide to Supabase RLS walks through the policies, and every table needs RLS covers the "one I forgot" case that causes most of these.

Where GuardLayer fits

Almost every incident above is statically visible before it ships: a disable row level security in a migration, a table created with no policy, a service_role key behind a NEXT_PUBLIC_ variable. GuardLayer scans a Next.js + Supabase repo for exactly those on every push and flags them with the fix — so the "RLS off" table gets caught in review instead of by a stranger with curl. It's the same class of mistake that produced the AI-built app leaks; the point is to catch it in the diff.

FAQ

Has Supabase been hacked or breached? Not the platform itself — there's no known compromise of Supabase's infrastructure. The incidents people call "Supabase breaches" are apps built on Supabase that left Row Level Security off, exposing their own users' data through the public anon key.

What was CVE-2025-48757? A May 2025 disclosure that 303 endpoints across 170 Lovable-generated apps had Supabase tables readable via the public anon key because RLS was never enabled. It carries a CVSS 9.3 on the CVE record; Lovable disputes attributing it to the platform rather than developer configuration.

Is my Supabase app exposed? Run select tablename from pg_tables where schemaname = 'public' and not rowsecurity; — anything returned is reachable by the anon key. If you didn't intend that table to be public, enable RLS and add a policy immediately.

Does enabling RLS fix it? Yes — enable RLS and add a policy granting the access you actually need (usually using ( (select auth.uid()) = user_id )). Never "fix" a blocked query by disabling RLS; that re-opens the table to everyone.

Are newer Supabase projects safer by default? Yes. From 2026, new projects don't expose public schema tables through the Data API by default, which closes the instant-exploit path. Existing projects and any table you deliberately expose still need RLS checked by hand.

Catch this before it ships — free

GuardLayer scans every push for this and 23 other Next.js + Supabase issues, with the exact fix inline.

No signup, no card — your code is scanned in memory and never stored.

Keep reading