CVE-2025-48757 Explained: How 170 Apps Leaked Through One Missing Policy
CVE-2025-48757 explained for non-developers: how 170 Lovable-built apps leaked real data through missing Supabase RLS — and how to check if yours did too.
If you built your app on Lovable and then saw "CVE-2025-48757" in a security thread or a scanner report, the name alone is enough to make your stomach drop. A CVE is an official, public record of a known security flaw. Seeing one attached to the exact tool you used feels like being named in a lawsuit you didn't know existed.
Take a breath. CVE-2025-48757 is not a bug in a single app, and it is not something a hacker did to you specifically. It's the first official write-up of a pattern — a default that affects a slice of apps built across the whole vibe-coding ecosystem. The good news is that the pattern is well understood, the check takes minutes, and the fix is usually a few lines of database configuration.
This post walks through what actually happened, what caused it, how to tell whether your app was in the affected group, and how to close the gap for good.
⚡ TL;DR
- CVE-2025-48757 is the first published CVE for a now-common pattern: AI-built Supabase apps shipping tables with missing or "allow everyone" Row Level Security (RLS), which lets anyone read the data through the app's public API.
- The leak does not happen because the public anon key is visible — that key is meant to be public. It happens because the database has no rule restricting which rows each visitor can see.
- The same pattern shows up on Bolt, v0, Cursor, and Replit. Checking your own app takes about five minutes, and we'll show you how.
What happened
In May 2025, security researcher Matt Palmer disclosed CVE-2025-48757 — the first published CVE for what has since become the signature security gap in AI-built apps.
The finding came from a scan of 1,645 apps built with Lovable. Of those, 170 apps — about 10.3% — were leaking real user data. The leaks spanned 303 endpoints, and the data came out through each app's public anon key hitting database tables that had missing or USING(true) RLS policies.
Two terms there matter, so let's define them plainly:
- Anon key — the public API key your app ships in the browser so it can talk to your Supabase database. Anyone who opens your site can read this key. That is by design (more on why below).
- RLS (Row Level Security) — a rule the database attaches to every query, deciding which rows each visitor is allowed to see.
USING(true)is a policy that matches every row, which is the same as having no protection at all.
So the picture is this: 170 apps had tables full of real user data, reachable through the public API, with no rule saying "this person can only see their own records." Anyone who knew where to look could pull the data straight out. No password cracking, no clever exploit — the front door was unlocked.
What made this a landmark wasn't the count. It was that it became the first published CVE for the category, turning a quiet, recurring mistake into a documented, named flaw. And the pattern is not unique to Lovable. The same missing-RLS shape recurs in apps generated by Bolt, v0, Cursor, and Replit, because they all default to Supabase as the backend and all optimize for "the feature works in the preview" over "the data is locked down."
The root cause (and the part everyone gets wrong)
Here's where most coverage of CVE-2025-48757 goes sideways, and where we want to be careful.
When data leaks from a Supabase app, it comes out through the anon key. So the natural panic reaction is: "My API key was exposed — that's the vulnerability. I need to rotate it."
That's not the bug. The anon key is public by design. Supabase built its entire permission model assuming this key is visible to everyone who loads your app. Rotating it does nothing for your security, because a new public key is every bit as public as the old one.
🐺 Not a real problem
An exposed Supabase anon key is not what caused CVE-2025-48757. The key is supposed to be public. If a scanner is telling you to rotate your anon key, it's crying wolf. The real flaw is tables with missing or
USING(true)RLS — a database with no rule restricting who sees which rows.
Think of the anon key as the handle on your front door. Everyone can see it and grab it. That's fine — that's what a door handle is for. RLS is the lock. CVE-2025-48757 happened because, on 170 apps, the lock was missing. The handle being visible was never the problem.
This distinction matters for a practical reason: if you "fix" the wrong thing — rotating keys, hiding the API URL — you'll feel safer while the actual hole stays wide open. The only fix that closes it is putting a real RLS policy on every table that holds user data.
Were you affected — how to check
Being built with Lovable does not mean your app leaked. It means your app could be in the same category that was scanned. Whether your tables are exposed depends entirely on whether they have working RLS. Here's how to find out in about five minutes.
- Open your Supabase dashboard → Database → Tables (or Authentication → Policies). Look at every table that stores user data — profiles, messages, orders, uploads, anything personal. Each one should show RLS enabled. A table with real data and "RLS disabled" is the exact condition behind this CVE.
- Read the policy, not only the on/off switch. A table can show "RLS enabled" and still leak if its only policy is
USING (true). That phrase means "this rule matches every row" — protection in name only. (We cover this exact trap in depth in the USING(true) trap.) - Test as an anonymous visitor. The most honest check is to query your public API with only the anon key — no login — and see what comes back. If you can pull other people's rows that way, so can anyone on the internet.
If all your user tables show RLS enabled with policies that tie rows to a specific user, you were almost certainly not in the affected 10%. If you find a table that's off, or one using USING(true), treat it as a live leak and move to the fix below.
Not sure if your app has this exact issue?
Run a free, read-only scan of your live app — no install, results in under a minute.
Scan my app free →The fix
If you find an exposed table, the remediation is short. Enable RLS, then add a policy that ties each row to its owner. For a typical "users only see their own records" table:
-- 1. Turn on Row Level Security for the table
alter table profiles enable row level security;
-- 2. Let a user read only their own row
create policy "Users read own profile"
on profiles for select
using ( auth.uid() = user_id );
-- 3. Let a user write only their own row
create policy "Users write own profile"
on profiles for insert
with check ( auth.uid() = user_id );
The line doing the real work is using ( auth.uid() = user_id ) — that's the per-user filter the database applies to every query. Avoid using ( true ), which is the policy that caused the leaks in the first place.
If you're working through an AI builder, you can hand it a prompt like this: "Enable RLS on every table that stores user data, and add policies so each user can only read and write rows where user_id equals their auth.uid(). Do not use USING(true) on any policy." Then verify the result by re-running the anonymous-visitor check above — don't take the AI's word that it's done.
How Is My Site Hackable? catches this class
CVE-2025-48757 was found by scanning live apps the way an attacker would — hitting real endpoints with the public key and seeing what data came back. That's exactly the approach a deployed-app scan takes, and it's why it catches this class of issue that a quick dashboard glance can miss.
Is My Site Hackable? queries your live endpoints with an anonymous request, the same as any visitor, and reports which tables actually return data they shouldn't. Because it tests behavior rather than reading config, it catches the USING(true) trap that looks protected in the dashboard. And it's built around the differentiation that matters here: it won't flag your anon key as a leak, because the anon key isn't the problem. It tells you which tables are truly exposed, and which warnings are false alarms — so you fix what's real and ignore the noise.
FAQ
Does CVE-2025-48757 mean Lovable is unsafe?
No. The CVE documents a pattern that comes from how AI builders default to Supabase and prioritize working demos, not a flaw unique to Lovable. The same missing-RLS shape appears in apps from Bolt, v0, Cursor, and Replit. A Lovable app with proper RLS policies is not affected; an app on any of these tools without RLS is.
Should I rotate my Supabase anon key because of this CVE?
No. The anon key is public by design and rotating it does nothing for this issue. The leak comes from tables without a real RLS policy, not from the key being visible. The one key you must keep secret is the service_role key, which bypasses RLS entirely — but that's a separate concern.
How do I know if my specific app was one of the 170?
The scan that found the 170 was a point-in-time research project, not a public list, so there's no roster to look yourself up on. What matters now is the state of your own tables today: check whether each user-data table has RLS enabled with a per-user policy, and test as an anonymous visitor. That tells you whether you're exposed regardless of any past scan.
The bottom line
CVE-2025-48757 turned a quiet, recurring mistake into a named, public flaw: AI-built Supabase apps shipping tables without a real Row Level Security policy, leaking user data through the public API. The visible anon key was never the problem — the missing lock was. An attacker can find an unprotected table in minutes by reading your app's network traffic, which is precisely how this CVE was found in the first place. The point is to find it first, and to keep checking, because your AI ships new tables — and new gaps — every time you add a feature.
Find your gaps before an attacker does.
Is My Site Hackable? scans your deployed app for the exact issues in this article — exposed keys, missing RLS, open buckets — and tells you what's real and what's a false alarm.
Run a free scan →