Supabase Security Check for AI-Built Apps
Zusammenfassung
Pixel shares research on database exposure risks in AI-built apps and a one-command check to verify Supabase security. Researchers found 24,664 of 159,041 scanned Lovable projects sent database records to visitors, often due to Row Level Security being disabled; the findings have important limits and do not establish misuse.
DEV Community
24,664 AI-built apps sent database records to any visitor. I built a one-command check that proves yours does not.
24,664 AI-built apps sent database records to any visitor. I built a one-command check that proves yours does not. In November 2026, German security firm Crissy Field (Hamburg), working with the newspaper Handelsblatt, published research on AI-built apps. The numbers are the reason I built this tool, so here they are first, with the caveats attached. The researchers scanned 159,041 Lovable projects found in Common Crawl (apps created December 2025 to September 2026). Of those, 34,545 used Supabase as their backend. 24,664 websites sent database records to the browser as soon as the page loaded, without any login or interaction. With further read-only requests using the same public key the app itself ships, the researchers found records containing email addresses in 10,560 tables across 7,403 sites (30%). Worst cases, each a separate app: one service provider exposed more than 1,000 identity records (passport numbers, expiry dates, nationalities); one lifestyle forum exposed more than 200,000 private chat messages and 80,000 profiles; one app exposed about 280,000 customer emails. Read those numbers honestly, because the researchers are explicit about the limits: 30% is NOT a confirmed leak rate for all Lovable apps. The sample is not representative, some email addresses are public contact or test data, and records without an email address were not counted. The researchers could not establish whether any exposed data was misused. Record counts are a floor, not a total: only part of each dataset was retrieved. This was not a hack of Lovable's systems. The researchers used read-only requests with the same public key the app itself ships. The root cause is Row Level Security left off in the app's Supabase database, with the public anon key doing the rest. The same class of bug had already been disclosed eight months earlier as CVE-2025-48757 (March 2025, CVSS 9.3): researchers scanned 1,645 Lovable showcase sites and found 170 with tables open to anonymous reads. Lovable added a Security Scanner and an AI Security Reviewer after that, and the exposure repeated at a larger scale in November. The lesson is not "run a scanner once". It is "prove, on every deploy, that an anonymous request returns zero rows". I built a small tool that does exactly that. It is called vibeleak, and it is a zero-dependency TypeScript CLI. MIT licensed. It starts from only the deployed app URL, finds the Supabase project URL and anon key in the JavaScript the app already ships, then probes each table and storage bucket as an anonymous visitor. One command, one verdict: CLEAN, LEAK, or REVIEW, with a JSON report and a baseline diff so a closed table that opens again fails CI. The problem: the key is already public, and nobody checked the lock When an AI tool builds an app on Supabase, it ships a public anon key in the frontend JavaScript. That is by design: the browser needs the key to talk to the database. The only thing standing between a stranger and your tables is Row Level Security. If RLS is off, or a policy says USING (true), the anon key reads the whole table, and the app helpfully sends the rows to any visitor on page load. Nobody checks this because the app works. The login page looks right, the dashboard loads, the data is there for the right user. The failure is invisible from inside the app. You only see it when you make the same request the app makes, without logging in, and count the rows that come back. That is what vibeleak does. It fetches the app the way any visitor does, extracts the Supabase URL and anon key from the shipped JavaScript (the same code every browser downloads), enumerates the tables through the PostgREST OpenAPI document, and probes each one with an anonymous GET limited to one row. It stores column names and a 0/1 rows-visible flag only. It never stores row values. It never writes anything: GET and HEAD only, no POST, no RPC calls, no writes of any kind. What it does Five commands: vibeleak scan [--i-own-t...

Powered by Readybot.io