CVE-2025-48757 to oceniona jako krytyczna podatność w Lovable (CVSS 9.3), która odsłoniła ponad 170 aplikacji. Problem: każdy, bez logowania, mógł odczytać — a w wielu przypadkach zmodyfikować — dane w twojej bazie: imiona i nazwiska, adresy e-mail, klucze API firm trzecich, a nawet status płatności. Źródłem problemu nie jest ukryty błąd Lovable, lecz wzorzec wspólny niemal każdej aplikacji tworzonej w stylu „vibe-coding": powierzenie całego bezpieczeństwa bazy danych politykom RLS w Supabase… i pozostawienie ich niekompletnymi.
Co się właściwie stało
Lovable buduje aplikacje, w których przeglądarka rozmawia bezpośrednio z bazą danych (Supabase) za pomocą wywołań REST, używając publicznego klucza anon. To rozsądny projekt, o ile każda tabela ma polityki Row-Level Security (RLS) decydujące o tym, które wiersze każdy użytkownik może odczytać lub zmienić. Podatność pojawiła się, ponieważ wiele projektów było wdrażanych z tabelami, które miały brak RLS albo niewystarczające RLS. Atakującemu wystarczyło zmodyfikować zapytanie REST — zmienić filtr w adresie URL — żeby poprosić o „wszystkie wiersze" tabeli, która powinna być chroniona.
Zgłosili to w marcu 2025 roku Matt Palmer i Kody Low oraz niezależnie Danial Asaria, a publiczne ujawnienie nastąpiło 29 maja 2025 roku (analiza techniczna, wpis CVE). Zagrożony mógł być każdy projekt Lovable używający bazy danych utworzonej 15 kwietnia 2025 roku lub wcześniej.
Dlaczego dotyczy to ciebie, nawet jeśli nie używasz Lovable
To nie jest problem wyłącznie Lovable. Każda aplikacja, która rozmawia z Supabase bezpośrednio z przeglądarki — niezależnie od tego, czy zbudowałeś ją w Bolt, v0, Cursor czy ręcznie — polega na tym, że RLS jest poprawne w każdej tabeli. Aplikacja wygląda idealnie, logowanie działa, ale prawdziwe bezpieczeństwo mieszka w bazie danych, a nie w interfejsie. Ukrycie przycisku we frontendzie niczego nie chroni: zapytanie REST wciąż tam jest, dostępne dla każdego, kto wie, gdzie szukać.
Jak sprawdzić, czy twoja aplikacja jest podatna
- Otwórz DevTools (F12) → zakładka Network podczas korzystania z aplikacji i obserwuj wywołania do
*.supabase.co/rest/v1/. Skopiuj jeden z tych adresów URL, otwórz go w oknie incognito (bez sesji) i sprawdź, czy zwraca dane. - Spróbuj poprosić o zbyt wiele: jeśli wywołanie zwraca twoje dane, usuń filtr z adresu URL. Jeśli oddaje wiersze innych użytkowników, twoje RLS nie działa skutecznie.
- Sprawdź panel Supabase → Authentication → Policies. Każda tabela z prawdziwymi danymi, która pokazuje „RLS disabled" albo w ogóle nie ma polityki, to otwarte drzwi.
Jak to naprawić
- Włącz RLS w każdej tabeli, nie tylko w tych „ważnych". Zasada brzmi: domyślnie odmawiaj — bez polityki, która na coś pozwala, nikt się nie dostanie.
- Napisz jawne polityki dla każdej operacji (select/insert/update/delete) powiązane z
auth.uid(), tak aby każdy użytkownik ruszał tylko własne wiersze. - Nigdy nie używaj klucza
service_rolewe frontendzie: całkowicie omija on RLS. Ten klucz mieszka wyłącznie na serwerze. - Przetestuj ponownie krokiem z incognito powyżej: jeśli zapytanie bez sesji zwraca teraz pustkę albo błąd, jesteś na dobrej drodze.
Jak sprawdza to Scanaris
Scanaris skanuje twoją stronę w trybie tylko do odczytu i wykrywa odcisk palca tego wzorca: endpointy Supabase dostępne z przeglądarki, zbyt liberalne CORS, klucze i tokeny ujawnione w twoim JavaScript oraz dane serwowane przez aplikację bez sesji. Wklej swój adres URL, a w kilka sekund otrzymasz listę — uszeregowaną według wagi — tego, co jest na widoku, zanim znajdzie to ktoś inny.