// docs / baas security / supabase rls scanner
Skaner Supabase RLS: znajdź tabele z brakującymi lub uszkodzonymi zabezpieczeniami na poziomie wierszy
Zabezpieczenia na poziomie wierszy (RLS) to jedyne, co stoi między danymi klientów a internetem, gdy wydajesz aplikację opartą na Supabase. Narzędzia kodowania AI generują kod o kształcie RLS, który się kompiluje, jest wydawany i po cichu wycieka dane — tabele utworzone bez włączonego RLS, polityki, które czytają, ale nigdy nie ograniczają, predykaty, które porównują kolumnę z samą sobą. Ten artykuł pokazuje, co skaner Supabase RLS może udowodnić z zewnątrz, cztery uszkodzone formy RLS, które pojawiają się w aplikacjach kodowanych w stylu vibe, i jak przeskanować własne wdrożenie w mniej niż minutę.
Co może udowodnić zewnętrzne skanowanie RLS
Pasywne skanowanie RLS działa wobec punktu końcowego PostgREST, który Supabase udostępnia pod adresem https://[project].supabase.co/rest/v1/. Używa wyłącznie publicznego klucza anon — tego samego klucza, którego używa przeglądarka — i sondy w poszukiwaniu metadanych listy tabel, anonimowych odczytów i anonimowych zapisów. Nigdy nie uwierzytelnia się jako użytkownik i nigdy nie dotyka uprawnień roli serwisowej. Wszystko, co może zrobić, może zrobić nieuwierzytelniony atakujący w internecie.
Spoza bazy danych skaner może z dużą pewnością potwierdzić następujące:
- RLS jest wyłączony na tabeli. PostgREST zwraca wiersze dla anonimowego
SELECT, gdy RLS jest wyłączony lub gdy polityka zezwala. W obu przypadkach jest to znalezisko. - Anonimowa rola może listować tabele.
GET /rest/v1/z kluczem anon zwraca schemat OpenAPI dla każdej tabeli, na której rolaanonma jakiekolwiek uprawnienia. Aplikacje generowane przez AI często przyznająUSAGEna schemacie iSELECTna każdej tabeli, co ujawnia pełną mapę schematu, nawet gdy RLS odmawia rzeczywistych odczytów. - Anonimowa rola może wstawiać. Sondujący
POSTz przypuszczeniem co do kształtu kolumny zakończy się sukcesem, jeśli RLS nie ma politykiINSERTodmawiającej tego — nawet jeśliSELECTjest zablokowany. - Klucz roli serwisowej znajduje się w pakiecie przeglądarki. Sąsiednio do RLS: jeśli skaner znajdzie
SUPABASE_SERVICE_ROLE_KEYlub jakikolwiek JWT zrole: service_rolew pakiecie JavaScript, RLS jest bez znaczenia — posiadacz tego klucza omija każdą politykę.
Czego zewnętrzne skanowanie nie może udowodnić
Bądź uczciwy co do granic skanera. Zewnętrzne skanowanie RLS nie może odczytać tabeli pg_policies, plików migracji ani dokładnego predykatu żadnej polityki. Wyciąga wnioski z zachowania czarnej skrzynki, co oznacza, że czasami zgłosi znalezisko, które okaże się celowo publicznymi danymi (tabela newslettera marketingowego, publiczny katalog produktów). Raport FixVibe oznacza je jako średnie zaufanie, gdy skaner nie może rozróżnić intencji — przejrzyj nazwę tabeli i zdecyduj.
Cztery uszkodzone formy RLS, które produkują narzędzia AI
Kiedy skierujesz Cursor, Claude Code, Lovable lub Bolt na Supabase, te same cztery wzorce uszkodzonego RLS pojawiają się w tysiącach aplikacji. Każdy przechodzi sprawdzenie typów, kompiluje się i jest wydawany:
Forma 1: RLS nigdy nie został włączony
Najczęstszy tryb awarii. Migracja tworzy tabelę, ale programista (lub narzędzie AI) zapomina o ALTER TABLE ... ENABLE ROW LEVEL SECURITY. PostgREST z radością obsługuje całą tabelę każdemu, kto ma klucz anon. Naprawa: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;. FORCE nie jest opcjonalne — bez niego właściciel tabeli (i każda rola z własnością tabeli) omija RLS.
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;Forma 2: RLS włączony, brak polityk
Bardziej subtelna awaria. RLS jest włączony, ale polityki nie są napisane. Domyślnie w PostgreSQL jest odmowa, więc uwierzytelnieni użytkownicy nic nie widzą — i programista dodaje USING (true), aby aplikacja działała, co pozwala każdemu czytać wszystko. Naprawa: napisz politykę z zakresem przez auth.uid(): CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); oraz pasującą politykę INSERT/UPDATE/DELETE.
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);Forma 3: Polityka porównuje kolumnę z samą sobą
A copy-paste artefact. The developer writes <code>USING (user_id = user_id)</code> — which is always true — instead of <code>USING (auth.uid() = user_id)</code>. Type-checks pass; the policy permits every row. <strong>Fix:</strong> always compare a column to a function call (<code>auth.uid()</code>, <code>auth.jwt()->>'org_id'</code>, etc.), never to itself or to a constant.
Forma 4: Polityka na SELECT, ale nie na INSERT/UPDATE
Programista blokuje odczyty, ale zapomina o zapisach. Polityki RLS są na poziomie poleceń. FOR SELECT chroni tylko odczyty; anonimowy klient może nadal INSERT, jeśli żadna polityka tego nie odmawia. Naprawa: napisz politykę na polecenie lub użyj FOR ALL z jawnymi klauzulami USING i WITH CHECK.
Jak działa skaner FixVibe Supabase RLS
Kontrola baas.supabase-rls działa w trzech etapach, każdy z jawnymi poziomami zaufania:
- Etap 1 — pobieranie odcisków palców. Skaner przeszukuje wdrożoną aplikację, analizuje jej pakiet JavaScript i wyodrębnia adres URL projektu Supabase oraz klucz anon z konfiguracji środowiska wykonawczego. Bez zgadywania DNS, bez brute force — czyta to, co czyta przeglądarka.
- Etap 2 — odkrycie schematu. Pojedynczy
GET /rest/v1/z kluczem anon zwraca schemat OpenAPI dla każdej tabeli, którą może zobaczyć rola anon. Skaner zapisuje nazwy tabel, ale na tym etapie nie odczytuje danych wierszy. - Etap 3 — sondy odczytu i zapisu. Dla każdej odkrytej tabeli skaner wysyła jeden anonimowy
SELECTzlimit=1. Jeśli wiersze są zwracane, RLS jest permisywny. Skaner się tam zatrzymuje — nie wylicza wierszy, nie stronicuje, nie modyfikuje danych. Sondy INSERT są zabezpieczone potwierdzoną własnością domeny i jawną zgodą; nigdy nie są uruchamiane wobec niezweryfikowanych celów.
Każde znalezisko jest dostarczane z dokładnym URL żądania, statusem odpowiedzi, kształtem odpowiedzi (tylko nagłówek) i nazwą tabeli. Podpowiedź naprawy AI na dole znaleziska to blok SQL z kopiowaniem i wklejaniem, który uruchamiasz w edytorze SQL Supabase.
Co zrobić, gdy skaner coś znajdzie
Każde znalezisko RLS to nagła sytuacja środowiska wykonawczego. Publiczne punkty końcowe PostgREST są skanowane przez atakujących w ciągu minut. Sekwencja naprawy jest mechaniczna:
- Sprawdź każdą tabelę. Uruchom
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';w edytorze SQL Supabase. Każdy wiersz zrowsecurity = falsejest problemem. - Włącz RLS na każdej publicznej tabeli. Domyślnie
ENABLE ROW LEVEL SECURITYiFORCE ROW LEVEL SECURITYna każdej tworzonej tabeli — uczyń to szablonem migracji. - Twórz polityki polecenie po poleceniu. Nie używaj
FOR ALL USING (true). Pisz jawne polityki dla SELECT, INSERT, UPDATE, DELETE — każdą z zakresem doauth.uid()lub kolumny org-id zauth.jwt(). - Zweryfikuj z drugim kontem. Zarejestruj się jako inny użytkownik, spróbuj odczytać rekordy innego użytkownika bezpośrednio przez REST API. Jeśli odpowiedź to
200, polityka jest uszkodzona. - Ponowne skanowanie. Po zastosowaniu naprawy uruchom ponownie skanowanie FixVibe wobec tego samego URL. Znalezisko
baas.supabase-rlspowinno zniknąć.
-- Audit every table for missing RLS. Run in the Supabase SQL editor.
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY rowsecurity, tablename;Jak to się ma do innych skanerów
Większość ogólnych narzędzi DAST (Burp Suite, OWASP ZAP, Nessus) nie wie, czym jest PostgREST. Przeszukują Twoją aplikację, ignorują ścieżkę /rest/v1/ i raportują o stronach HTML, które rozumieją. Snyk i Semgrep to narzędzia analizy statycznej — znajdują pliki migracji w Twoim repozytorium z brakującymi wywołaniami RLS, ale nie mogą udowodnić, że wdrożona baza danych jest błędnie skonfigurowana. FixVibe siedzi w tej luce: pasywny, świadomy BaaS, skupiony na tym, co nieuwierzytelniony atakujący może udowodnić z publicznego URL.
Często zadawane pytania
Czy skaner odczyta lub zmodyfikuje moje dane?
Nie. Pasywne skanowania wysyłają co najwyżej jeden SELECT ... limit=1 na odkrytą tabelę, aby potwierdzić, czy RLS zezwala na anonimowe odczyty. Skaner zapisuje kształt odpowiedzi, a nie zawartość wierszy. Sondy INSERT, UPDATE i DELETE są zabezpieczone potwierdzoną własnością domeny i nigdy nie działają wobec niezweryfikowanych celów.
Czy działa, jeśli mój projekt Supabase jest wstrzymany lub na niestandardowej domenie?
Wstrzymane projekty zwracają 503 przy każdym żądaniu — skaner zgłasza projekt jako nieosiągalny. Niestandardowe domeny działają, dopóki wdrożona aplikacja nadal ładuje SDK klienta Supabase w przeglądarce; skaner i tak wyodrębnia URL projektu z pakietu.
Co jeśli mój klucz anon zostanie obrócony lub mój klucz publiczny się zmieni?
Uruchom ponownie skan. Skaner ponownie wyodrębnia klucz z bieżącego pakietu przy każdym uruchomieniu. Rotacja unieważnia tylko poprzedni raport, a nie stan polityki bazy danych.
Czy skaner sprawdza nowy model klucza publicznego Supabase (<code>sb_publishable_*</code>)?
Tak. Detektor rozpoznaje zarówno starsze JWT anon, jak i nowsze klucze sb_publishable_* i traktuje je identycznie — oba są przeznaczone do bycia publicznymi i oba pozostawiają RLS jako jedyną linię obrony.
Następne kroki
Uruchom bezpłatne skanowanie FixVibe wobec swojego produkcyjnego URL — kontrola baas.supabase-rls jest włączona na każdym planie, w tym na bezpłatnym poziomie. Aby uzyskać głębsze odczytanie tego, co jeszcze może wyciec z projektu Supabase, zobacz Klucz roli serwisowej Supabase ujawniony w JavaScript i Lista kontrolna bezpieczeństwa kosza magazynu Supabase. Aby uzyskać widok parasolowy obejmujący wszystkich dostawców BaaS, przeczytaj Skaner błędnych konfiguracji BaaS.
