ok so people are freaking out about the crissy field lovable writeup and… yeah. the numbers are rough.
they looked at 159,041 lovable projects. 34,545 used supabase. 24,664 of the ones they dug into were already shipping database records on first page load with no login. that alone is not automatically a bug — some of that data is meant to be public. they then made additional read-only requests with the same public key and found emails in 10,560 tables across 7,403 of those sites, plus examples that go past contact forms (passports, chat messages, tickets).
full piece, including their limitations section: https://www.crissyfield.de/research/lovable-en/
two caveats from their writeup that more people should repeat:
- “data on first paint” ≠ “confirmed leak.”
- the ~30% figure is not a confirmed leak rate for all lovable apps. it only applies to the 24,664 sites they examined more closely, the sample came from common crawl, and they only pulled parts of each dataset.
what i keep telling people building with lovable / cursor / bolt / v0: the scary part usually isn’t “i leaked the supabase anon key.” that key is supposed to be in the browser. the scary part is missing or wide-open row level security. a public anon key is not a secret. a service_role key in client code is.
what an outside check can (and can’t) see
i built hackorbroke.com for that launch moment. one polite, read-only pass against a live url you own.
from the outside it fetches your homepage and a few same-site scripts; looks for supabase urls + anon / service_role tokens in browser-visible code; treats service_role in client code as a hard fail; treats a normal anon key as “expected, but go verify RLS” — because it does not query your tables; and checks boring stuff people skip (.env, .git/config, robots/sitemap, headers, http→https, obvious ai spend traps).
drop a public github repo in and it also does a static code read: migrations that never enable rls, write policies open to everyone, supabase functions with verify_jwt = false next to the service role, server routes that call paid ai apis with no sign-in / rate limit. still no live db reads, no password guessing, no exploit testing.
that’s the honest limit. crissy field went further than a pre-launch checker should. an outside scan is the “did i leave the door labeled?” check — not a pentest, not a guarantee, and not a claim that every unauthenticated route is a bug. some public endpoints are intentional.
what to do this week if you shipped a lovable + supabase app
- open supabase → table editor. every table with personal data needs rls on, with policies that match how users sign in.
- rotate anything that was ever a
service_rolein the client. - assume “data on first paint” is public unless you can explain why it shouldn’t be.
- run a free outside scan anyway. it’s free, redacts secrets, and gives a fix prompt you can paste back into lovable / cursor.
i’m not dunking on lovable. the gap is the same one every weekend app has: auth and access rules are easy to forget when the ui looks done.
short version: public anon key ≠ safe database. rls is the product.
soft ask: paste your preview or prod url into https://hackorbroke.com, check the box that you own it, and run the free scan before real users land. if something’s loud, fix that first. if it’s quiet, still stare at the rls toggles.


