// CVE-2025-48757 · CVSS 9.3 Critical

One lunch break to read every user's data. here's how.

CVE-2025-48757 left 170+ Lovable apps wide open by shipping with Supabase Row Level Security off. The public key in the page became a skeleton key to the whole database — names, phone numbers, payments, even other API keys — no login required.

CVE ID

CVE-2025-48757

Severity

CVSS 9.3 — Critical

Platform

Lovable (Supabase backend)

Disclosed

May 2025

Check if your app is exposed — free, ~60 seconds, no signup.

What CVE-2025-48757 actually is

Lovable builds apps on Supabase. To talk to the database from the browser, every Lovable app embeds the Supabase project URL and the anon (public) key directly in the page. That is by design — and safe only if Row Level Security (RLS) is enabled on every table.

RLS is the gate. With it on, the public key can only see rows a policy explicitly allows. With it off, the public key can read and write everything. CVE-2025-48757 is the vulnerability class where that gate was simply never closed — across hundreds of shipped Lovable apps.

How the attack works

  1. 1

    Open any Lovable app and look at the network tab. The Supabase URL and anon key are right there in the requests — they have to be, for the app to work.

  2. 2

    Copy the key and send your own query straight to the Supabase REST API, skipping the app's UI entirely.

  3. 3

    If RLS is off on a table, the API returns every row. Change the query and you can read full user lists, payment records, phone numbers, and even other services' API keys.

  4. 4

    Because writes go through the same path, an attacker can also insert or modify data — no login, no exploit code, no special skill.

How big was it

170

apps found exposed out of 1,645 scanned

10.3%

of analysed Lovable projects affected

303

insecure endpoints leaking data

Figures from security researcher Matt Palmer, who crawled 1,645 Lovable-powered projects in May 2025. The exposed data included names, phone numbers, subscriptions, payment details, and live API keys (Google Maps tokens and more).

How to fix it

Enable RLS on every table, then write a policy that scopes rows to the logged-in user. In the Supabase SQL editor:

-- 1. Turn on Row Level Security
alter table public.profiles enable row level security;

-- 2. Only let users read their own rows
create policy "Users read own profile"
on public.profiles
for select
using ( (select auth.uid()) = user_id );

-- Repeat for every table. Wrapping auth.uid() in a
-- subselect — (select auth.uid()) — keeps it fast at scale.
Tables created with the Supabase Table Editor get RLS on by default — manually-created tables do NOT. Those are the ones that get missed.
A policy of `using (true)` defeats the purpose — scope to the user.
Never put the service_role key in client code; it bypasses RLS entirely.
After fixing, re-scan to confirm no table still returns data to the anon key.

FAQ

What is CVE-2025-48757?

It's a critical (CVSS 9.3) vulnerability class in Lovable-built apps where Supabase Row Level Security (RLS) was missing or misconfigured. Because the public anon key is embedded in the front-end, anyone could query the database directly and read or modify data without logging in.

Is my Lovable app affected?

If any table in your Supabase project doesn't have RLS enabled with correct policies, yes — your data is reachable with the public key. The fastest way to know is to query your tables the way an attacker would. bleek's free scan does exactly that in about a minute.

Is it safe to expose the Supabase anon key?

Yes, but only when RLS is on. The anon key is designed to be public; RLS is what's supposed to stop it from reading data it shouldn't. CVE-2025-48757 is what happens when that gate is missing.

How do I fix it?

Enable RLS on every table and write policies that scope rows to the authenticated user (for example, using auth.uid() = user_id). Tables made with the Supabase Table Editor get RLS on by default, but manually-created tables do not — those are the ones that bite.

Is your app one of them?

bleek probes your tables with the public key, exactly the way this attack does — and tells you which are exposed, free.