CVE-2025-48757 is een als kritiek beoordeelde kwetsbaarheid in Lovable (CVSS 9.3) die meer dan 170 applicaties blootlegde. Het probleem: iedereen kon, zonder in te loggen, data in jouw database lezen —en in veel gevallen aanpassen—: namen, e-mailadressen, API-sleutels van derden, zelfs de betaalstatus. De oorzaak is geen verborgen bug in Lovable, maar een patroon dat bijna elke "vibe-coded" app deelt: alle databasebeveiliging toevertrouwen aan de RLS-policies van Supabase… en ze onvolledig laten.
Wat er echt gebeurde
Lovable bouwt apps waarin de browser rechtstreeks met de database (Supabase) praat via REST-calls, met de publieke anon-sleutel. Dat is een prima ontwerp zolang elke tabel Row-Level Security (RLS)-policies heeft die bepalen welke rijen elke gebruiker mag lezen of aanraken. De kwetsbaarheid ontstond doordat veel projecten live gingen met tabellen die geen RLS of onvoldoende RLS hadden. Een aanvaller hoefde alleen de REST-request aan te passen —een filter in de URL veranderen— om "alle rijen" op te vragen van een tabel die beschermd had moeten zijn.
Het werd in maart 2025 gemeld door Matt Palmer en Kody Low, en onafhankelijk door Danial Asaria, met publieke bekendmaking op 29 mei 2025 (technische write-up, CVE-vermelding). Elk Lovable-project met een database die op of vóór 15 april 2025 is aangemaakt, kan getroffen zijn.
Waarom het jou raakt, zelfs als je Lovable niet gebruikt
Dit is geen probleem dat alleen Lovable treft. Elke app die rechtstreeks vanuit de browser met Supabase praat —of je die nu met Bolt, v0, Cursor of met de hand hebt gebouwd— vertrouwt erop dat RLS op elke tabel klopt. De app ziet er perfect uit, inloggen werkt, maar de echte beveiliging zit in de database, niet in de interface. Een knop verstoppen in de frontend beschermt niets: de REST-request staat er nog steeds voor iedereen die weet waar hij moet kijken.
Hoe je weet of jouw app kwetsbaar is
- Open DevTools (F12) → tabblad Network terwijl je jouw app gebruikt en kijk naar de calls naar
*.supabase.co/rest/v1/. Kopieer een van die URL's, open hem in een incognitovenster (zonder sessie) en kijk of er data terugkomt. - Probeer te veel op te vragen: als een call jouw data teruggeeft, verwijder dan het filter uit de URL. Als je dan de rijen van andere gebruikers terugkrijgt, werkt jouw RLS niet.
- Controleer het Supabase-dashboard → Authentication → Policies. Elke tabel met echte data die "RLS disabled" of helemaal geen policy toont, is een open deur.
Hoe je het oplost
- Zet RLS aan op elke tabel, niet alleen op de "belangrijke". De regel is standaard weigeren: zonder een policy die het toestaat, komt niemand binnen.
- Schrijf expliciete policies per operatie (select/insert/update/delete) gekoppeld aan
auth.uid(), zodat elke gebruiker alleen zijn eigen rijen aanraakt. - Gebruik de
service_role-sleutel nooit in de frontend: die omzeilt RLS volledig. Die sleutel hoort alleen op de server thuis. - Test opnieuw met de incognitostap hierboven: als de request zonder sessie nu leeg of een foutmelding teruggeeft, zit je goed.
Hoe Scanaris het controleert
Scanaris scant jouw site read-only en detecteert de vingerafdruk van dit patroon: Supabase-endpoints die vanuit de browser bereikbaar zijn, te permissieve CORS, sleutels en tokens die in jouw JavaScript blootliggen, en data die de app zonder sessie serveert. Plak jouw URL en het vertelt je, in enkele seconden en gesorteerd op ernst, wat er in het volle zicht ligt —voordat iemand anders het vindt.