// docs / baas security / supabase rls scanner
Supabase RLS-skanner: leia tabelid, kus on puuduv või katkine row-level security
Row-level security (RLS) on ainus asi, mis eraldab sinu klientide andmeid internetist, kui sa avaldad Supabase-põhise rakenduse. AI-koodimistööriistad tekitavad RLS-kujulist koodi, mis kompileerub, juurutub ja lekib andmeid vaikselt — tabelid luuakse ilma RLS-i lubamata, poliitikad, mis loevad, kuid ei piira kunagi, predikaadid, mis võrdlevad veergu iseendaga. See artikkel näitab, mida Supabase RLS-skanner suudab väljast tõestada, neli katkise RLS-i kuju, mis vibe-koodisuse rakendustes esile kerkivad, ja kuidas oma juurutust alla minuti skannida.
Mida väline RLS-skannimine suudab tõestada
Passiivne RLS-skannimine käivitatakse PostgRESTi otspunkti vastu, mille Supabase avaldab aadressil https://[project].supabase.co/rest/v1/. See kasutab ainult avaldatavat anon-võtit — sama, mida sinu brauser kasutab — ja sondeerib tabeliloendi metaandmeid, anonüümseid lugemisi ja anonüümseid kirjutamisi. See ei autendi end kunagi kasutajana ega puuduta kunagi service-role'i õigusi. Kõik, mida see suudab teha, suudab teha ka tundmatu ründaja internetis.
Andmebaasi väljast saab skanner kinnitada järgmist suure kindlusega:
- RLS on tabelil välja lülitatud. PostgREST tagastab read anonüümsele
SELECT-päringule, kui RLS on välja lülitatud või kui poliitika seda lubab. Mõlemad juhud on leid. - Anonüümne roll suudab tabeleid loetleda.
GET /rest/v1/anon-võtmega tagastab OpenAPI skeemi iga tabeli kohta, millel rollilanonon mingi õigus. AI-genereeritud rakendused annavad sageli skeemileUSAGEja igale tabelileSELECT, mis paljastab kogu skeemikaardi isegi siis, kui RLS tegelikud lugemised keelab. - Anonüümne roll suudab INSERT-operatsiooni teha. Sondeeriv
POSToletusega veerukuju kohta õnnestub, kui RLS-il ei oleINSERT-poliitikat, mis seda keelab — isegi kuiSELECTon lukustatud. - Service-role'i võti on brauseripakis. RLS-i kõrval: kui skanner leiab JavaScripti pakist
SUPABASE_SERVICE_ROLE_KEYvõi mistahes JWT, milles onrole: service_role, on RLS sisutu — selle võtme omanik möödub kõikidest poliitikatest.
Mida väline skannimine ei suuda tõestada
Ole skanneri piiride suhtes aus. Väline RLS-skannimine ei suuda lugeda sinu pg_policies-tabelit, sinu migratsioonifaile ega ühegi poliitika täpset predikaati. See järeldab black-box-käitumisest, mis tähendab, et see teatab vahel leiust, mis osutub kavatsetud avalikuks andmeks (turunduse uudiskirjatabel, avalik tooteloend). FixVibe aruanne märgib need kui keskmise kindlusega, kui skanner ei suuda kavatsust eristada — vaata tabeli nime ja otsusta.
Neli katkise RLS-i kuju, mida AI-tööriistad tekitavad
Kui sa suunad Cursori, Claude Code'i, Lovable'i või Bolti Supabase'i poole, korduvad samad neli katkise RLS-i mustrit tuhandetes rakendustes. Iga neist läbib tüübikontrolli, kompileerub ja juurutub:
Kuju 1: RLS-i pole kunagi sisse lülitatud
Kõige sagedasem ebaõnnestumine. Migratsioon loob tabeli, kuid arendaja (või AI-tööriist) unustab ALTER TABLE ... ENABLE ROW LEVEL SECURITY. PostgREST serveerib kogu tabeli rõõmsalt kõigile, kellel on anon-võti. Parandus: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;. FORCE pole valikuline — ilma selleta möödub tabeli omanik (ja iga roll, kellel on tabeli omandus) RLS-ist.
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;Kuju 2: RLS on sees, poliitikaid pole
Peenem viga. RLS on sees, kuid poliitikaid ei ole kirjutatud. PostgreSQL-i vaikimisi väärtus on keeld, seega autenditud kasutajad ei näe midagi — ja arendaja lisab USING (true), et rakendus tööle saaks, mis lubab igal ühel kõike lugeda. Parandus: kirjuta poliitika, mis piirab auth.uid()-iga: CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); ja vastav INSERT/UPDATE/DELETE-poliitika.
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);Kuju 3: Poliitika võrdleb veergu iseendaga
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.
Kuju 4: Poliitika SELECT-ile, aga mitte INSERT/UPDATE-ile
Arendaja lukustab lugemised, kuid unustab kirjutamised. RLS-poliitikad on käsupõhised. FOR SELECT kaitseb ainult lugemisi; anonüümne klient võib endiselt teha INSERT-i, kui ükski poliitika seda ei keela. Parandus: kirjuta käsu kohta üks poliitika või kasuta FOR ALL selgesõnaliste USING- ja WITH CHECK-klauslitega.
Kuidas FixVibe Supabase RLS-skanner töötab
Kontroll baas.supabase-rls käivitatakse kolmes etapis, igas selgesõnaline kindlustase:
- Etapp 1 — sõrmejälgede võtmine. Skanner roomab juurutatud rakendust läbi, parsib selle JavaScripti paki ja eraldab käituskonfiguratsioonist Supabase-projekti URL-i ja anon-võtme. DNS-oletust pole, brute force'i pole — see loeb seda, mida loeb sinu brauser.
- Etapp 2 — skeemi avastamine. Üks
GET /rest/v1/anon-võtmega tagastab OpenAPI skeemi iga tabeli kohta, mida anon-roll näeb. Skanner salvestab tabelite nimed, kuid ei loe selles etapis rea-andmeid. - Etapp 3 — lugemis- ja kirjutamissondid. Iga avastatud tabeli jaoks saadab skanner ühe anonüümse
SELECT-i parameetrigalimit=1. Kui read tagastatakse, on RLS lubav. Skanner peatub seal — see ei loenda ridu, ei lehekülganda ega muuda andmeid. INSERT-sondid on piiratud kinnitatud domeeniomandi ja selgesõnalise nõusoleku taha; neid ei käivitata kunagi kinnitamata sihtmärkide vastu.
Iga leid tarnitakse täpse päringu-URL-i, vastuse staatuse, vastuse kuju (ainult päised) ja tabeli nimega. AI-paranduskäsk leidu lõpus on kopeeri-kleebi SQL-plokk, mida käivitada Supabase SQL-toimetajas.
Mida teha, kui skanner midagi leiab
Iga RLS-leid on käituskeskne hädaolukord. Avalikke PostgREST-otspunkte skannivad ründajad minutitega. Parandusjada on mehaaniline:
- Auditeeri iga tabel. Käivita
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';Supabase SQL-toimetajas. Iga rida, kusrowsecurity = false, on probleem. - Lülita RLS sisse igal avalikul tabelil. Vaikimisi seadista
ENABLE ROW LEVEL SECURITYjaFORCE ROW LEVEL SECURITYigale loodavale tabelile — tee sellest migratsioonimall. - Kirjuta poliitikad käsu kaupa. Ära kasuta
FOR ALL USING (true). Kirjuta selgesõnalised poliitikad SELECT-ile, INSERT-ile, UPDATE-ile, DELETE-ile — iga neist piiratudauth.uid()-iga või org-id-veerugaauth.jwt()-ist. - Kontrolli teise kontoga. Registreeru teise kasutajana, proovi REST API kaudu otse teise kasutaja kirjeid lugeda. Kui vastus on
200, on poliitika katki. - Skanni uuesti. Pärast paranduse rakendamist käivita FixVibe-skannimine uuesti sama URL-i vastu. Leid
baas.supabase-rlspeaks kaduma.
-- 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;Kuidas see võrdleb teiste skanneritega
Enamik üldiseid DAST-tööriistu (Burp Suite, OWASP ZAP, Nessus) ei tea, mis on PostgREST. Nad roomavad sinu rakendust läbi, ignoreerivad /rest/v1/-rada ja teatavad HTML-lehtedest, mida nad mõistavad. Snyk ja Semgrep on staatilise analüüsi tööriistad — nad leiavad sinu repos migratsioonifailid, kus RLS-kutsed puuduvad, kuid nad ei suuda tõestada, et juurutatud andmebaas on vääras seadistuses. FixVibe asub sellesse vahesse: passiivne, BaaS-teadlik, keskendunud sellele, mida tundmatu ründaja avalikust URL-ist tõestada suudab.
Korduma kippuvad küsimused
Kas skanner loeb või muudab minu andmeid?
Ei. Passiivsed skannimised saadavad iga avastatud tabeli kohta maksimaalselt ühe SELECT ... limit=1-päringu, et kinnitada, kas RLS lubab anonüümseid lugemisi. Skanner salvestab vastuse kuju, mitte ridade sisu. INSERT-, UPDATE- ja DELETE-sondid on piiratud kinnitatud domeeniomandi taha ja neid ei käivitata kunagi kinnitamata sihtmärkide vastu.
Kas see töötab, kui mu Supabase-projekt on peatatud või kohandatud domeenil?
Peatatud projektid tagastavad iga päringu peale 503 — skanner teatab projekti kättesaamatuna. Kohandatud domeenid toimivad seni, kuni juurutatud rakendus laadib Supabase'i klient-SDK ikka brauserisse; skanner eraldab projekti URL-i pakist nii ehk teisiti.
Mis siis, kui mu anon-võti pööratakse või mu avaldatav võti muutub?
Käivita skannimine uuesti. Skanner eraldab võtme praegusest pakist iga käivitusega uuesti. Pööramine muudab kehtetuks ainult eelmise aruande, mitte andmebaasi poliitikate seisundi.
Kas skanner kontrollib ka uut Supabase'i avaldatava võtme mudelit (<code>sb_publishable_*</code>)?
Jah. Detektor tunneb ära nii vanad anon-JWT-d kui ka uuemad sb_publishable_*-võtmed ja käsitleb neid identselt — mõlemad on mõeldud avalikuks ja mõlemad jätavad RLS-i ainsaks kaitseliiniks.
Järgmised sammud
Käivita tasuta FixVibe-skannimine oma tootmise URL-i vastu — kontroll baas.supabase-rls on sees igas plaanis, sealhulgas tasuta tasemel. Sügavamaks lugemiseks selle kohta, mis veel Supabase-projektist lekkida võib, vaata Supabase service-role'i võti paljastunud JavaScriptis ja Supabase salvestuskonteinerite turvalisuse kontrollnimekiri. Üldpildi saamiseks kõikide BaaS-pakkujate kohta loe BaaS väärseadistuse skanner.
