// docs / baas security / supabase rls scanner
Supabase RLS-skandeerder: vind tabelle met ontbrekende of stukkende ry-vlak-sekuriteit
Ry-vlak-sekuriteit (RLS) is die enigste ding wat tussen jou kliënte se data en die internet staan wanneer jy 'n Supabase-gerugsteunde toepassing publiseer. KI-koderingsgereedskap genereer RLS-vormige kode wat kompileer, publiseer en stilweg data lek — tabelle wat sonder RLS geaktiveer geskep is, beleide wat lees maar nooit beperk nie, predikate wat 'n kolom met homself vergelyk. Hierdie artikel wys wat 'n Supabase RLS-skandeerder van buite kan bewys, die vier stukkende-RLS-vorms wat in vibe-gekodeerde toepassings opduik, en hoe om jou eie ontplooiing in minder as 'n minuut te skandeer.
Wat 'n eksterne RLS-skandering kan bewys
'n Passiewe RLS-skandering loop teen die PostgREST-eindpunt wat Supabase blootstel by https://[project].supabase.co/rest/v1/. Dit gebruik slegs die publiseerbare anon-sleutel — dieselfde sleutel wat jou blaaier gebruik — en ondersoek tabellys-metadata, anonieme leesoperasies en anonieme skryfoperasies. Dit autentiseer nooit as 'n gebruiker nie en raak nooit aan diens-rol-bevoegdhede nie. Enigiets wat dit kan doen, kan 'n ongeautentiseerde aanvaller op die internet ook doen.
Van buite die databasis kan 'n skandeerder die volgende met hoë vertroue bevestig:
- RLS is op 'n tabel afgeskakel. PostgREST gee rye terug vir 'n anonieme
SELECTwanneer RLS af is of wanneer 'n beleid dit toelaat. Beide gevalle is 'n bevinding. - Die anonieme rol kan tabelle lys. 'n
GET /rest/v1/met die anon-sleutel gee die OpenAPI-skema terug vir elke tabel waarop dieanon-rol enige bevoegdheid het. KI-gegenereerde toepassings ken dikwelsUSAGEop die skema toe enSELECTop elke tabel, wat die volle skema-kaart blootstel selfs wanneer RLS die werklike leesoperasies weier. - Die anonieme rol kan invoeg. 'n Ondersoekende
POSTmet 'n raaiskoot na die kolomvorm sal slaag as RLS nie 'nINSERT-beleid het wat dit weier nie — selfs asSELECTtoegesluit is. - Die diens-rol-sleutel is in die blaaierbundel. Aangrensend aan RLS: as 'n skandeerder
SUPABASE_SERVICE_ROLE_KEYof enige JWT metrole: service_rolein die JavaScript-bundel vind, is RLS irrelevant — die houer van daardie sleutel omseil elke beleid.
Wat 'n eksterne skandering nie kan bewys nie
Wees eerlik oor die skandeerder se grense. 'n Eksterne RLS-skandering kan nie jou pg_policies-tabel, jou migrasie-lêers, of die presiese predikaat van enige beleid lees nie. Dit lei af uit swart-boks gedrag, wat beteken dit sal soms 'n bevinding rapporteer wat uiteindelik bedoelde publieke data is ('n bemarkingsnuusbrieftabel, 'n openbare produkkatalogus). Die FixVibe-verslag merk hierdie as medium vertroue wanneer die skandeerder nie bedoeling kan ontknoop nie — beoordeel die tabelnaam en besluit self.
Die vier stukkende-RLS-vorms wat KI-gereedskap voortbring
Wanneer jy Cursor, Claude Code, Lovable, of Bolt op Supabase rig, kom dieselfde vier stukkende-RLS-patrone in duisende toepassings na vore. Elkeen slaag tipe-kontrole, kompileer en publiseer:
Vorm 1: RLS is nooit geaktiveer nie
Die mees algemene falingsmodus. Die migrasie skep die tabel maar die ontwikkelaar (of die KI-gereedskap) vergeet ALTER TABLE ... ENABLE ROW LEVEL SECURITY. PostgREST bedien graag die hele tabel aan enigiemand met die anon-sleutel. Regstelling: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;. FORCE is nie opsioneel nie — sonder dit omseil die tabel-eienaar (en enige rol met tabel-eienaarskap) RLS.
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;Vorm 2: RLS geaktiveer, geen beleide nie
'n Meer subtiele faling. RLS is geaktiveer maar geen beleide is geskryf nie. Die verstek in PostgreSQL is weier, so geautentiseerde gebruikers sien niks — en die ontwikkelaar voeg USING (true) by om die toepassing te laat werk, wat almal toelaat om alles te lees. Regstelling: skryf 'n beleid wat met auth.uid() beperk: CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); en 'n ooreenstemmende INSERT/UPDATE/DELETE-beleid.
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);Vorm 3: Beleid vergelyk kolom met homself
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.
Vorm 4: Beleid op SELECT maar nie op INSERT/UPDATE nie
Die ontwikkelaar sluit leesoperasies toe maar vergeet skryfoperasies. RLS-beleide is per-opdrag. FOR SELECT beskerm slegs leesoperasies; 'n anonieme kliënt kan steeds INSERT as geen beleid dit weier nie. Regstelling: skryf 'n beleid per opdrag, of gebruik FOR ALL met eksplisiete USING en WITH CHECK-klousules.
Hoe die FixVibe Supabase RLS-skandeerder werk
Die baas.supabase-rls-toets loop in drie fases, elk met eksplisiete vertrouensvlakke:
- Fase 1 — vingerafdruk. Die skandeerder kruip deur die ontplooide toepassing, ontleed sy JavaScript-bundel, en onttrek die Supabase-projek-URL en anon-sleutel uit die looptyd-konfigurasie. Geen DNS-rateery, geen brute krag nie — dit lees wat die blaaier lees.
- Fase 2 — skema-ontdekking. 'n Enkele
GET /rest/v1/met die anon-sleutel gee die OpenAPI-skema terug vir elke tabel wat die anon-rol kan sien. Die skandeerder teken tabelname aan maar lees geen ry-data in hierdie fase nie. - Fase 3 — lees- en skryfondersoeke. Vir elke ontdekte tabel stuur die skandeerder een anonieme
SELECTmetlimit=1. As rye teruggegee word, is RLS toegeeflik. Die skandeerder stop daar — dit lys nie rye nie, paginate nie, en wysig nie data nie. INSERT-ondersoeke is agter geverifieerde domein-eienaarskap en eksplisiete intekening verskuil; hulle vuur nooit teen ongeverifieerde teikens nie.
Elke bevinding word verskaf met die presiese versoek-URL, antwoord-status, antwoordvorm (slegs kopstuk) en die tabelnaam. Die KI-regstellingsaanwysing onderaan die bevinding is 'n kopie-plak SQL-blok wat jy in die Supabase SQL-redigeerder uitvoer.
Wat om te doen wanneer die skandeerder iets vind
Elke RLS-bevinding is 'n looptyd-noodgeval. Openbare PostgREST-eindpunte word binne minute deur aanvallers geskandeer. Die regstellingsreeks is meganies:
- Oudit elke tabel. Voer
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';in die Supabase SQL-redigeerder uit. Enige ry metrowsecurity = falseis 'n probleem. - Aktiveer RLS op elke publieke tabel. Stel
ENABLE ROW LEVEL SECURITYenFORCE ROW LEVEL SECURITYas verstek op elke tabel wat geskep word — maak dit 'n migrasie-sjabloon. - Skryf beleide opdrag-vir-opdrag. Moenie
FOR ALL USING (true)gebruik nie. Skryf eksplisiete beleide vir SELECT, INSERT, UPDATE, DELETE — elkeen beperk totauth.uid()of 'n org-id-kolom uitauth.jwt(). - Verifieer met 'n tweede rekening. Teken aan as 'n ander gebruiker, probeer om 'n ander gebruiker se rekords direk via die REST-API te lees. As die antwoord
200is, is die beleid stukkend. - Herskandeer. Nadat die regstelling toegepas is, voer 'n FixVibe-skandering teen dieselfde URL weer uit. Die
baas.supabase-rls-bevinding behoort verwyder te wees.
-- 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;Hoe dit met ander skandeerders vergelyk
Die meeste generiese DAST-gereedskap (Burp Suite, OWASP ZAP, Nessus) weet nie wat PostgREST is nie. Hulle sal jou toepassing kruip, die /rest/v1/-pad ignoreer, en rapporteer oor die HTML-bladsye wat hulle wel verstaan. Snyk en Semgrep is statiese-analise-gereedskap — hulle vind migrasie-lêers in jou bewaarplek met ontbrekende RLS-oproepe, maar hulle kan nie bewys dat die ontplooide databasis wankonfigureer is nie. FixVibe sit in die gaping: passief, BaaS-bewus, gefokus op wat 'n ongeautentiseerde aanvaller vanaf die publieke URL kan bewys.
Algemene vrae
Sal die skandeerder my data lees of wysig?
Nee. Passiewe skanderings stuur hoogstens een SELECT ... limit=1 per ontdekte tabel om te bevestig of RLS anonieme leesoperasies toelaat. Die skandeerder teken die antwoordvorm aan, nie die ry-inhoud nie. INSERT-, UPDATE- en DELETE-ondersoeke is agter geverifieerde domein-eienaarskap verskuil en loop nooit teen ongeverifieerde teikens nie.
Werk dit as my Supabase-projek gepouseer is of op 'n pasgemaakte domein loop?
Gepouseerde projekte gee 503 terug op elke versoek — die skandeerder rapporteer die projek as onbereikbaar. Pasgemaakte domeine werk solank die ontplooide toepassing steeds die Supabase-kliënt-SDK in die blaaier laai; die skandeerder onttrek die projek-URL hoe ook al uit die bundel.
Wat as my anon-sleutel geroteer word of my publiseerbare sleutel verander?
Voer die skandering weer uit. Die skandeerder onttrek die sleutel weer uit die huidige bundel by elke uitvoering. Rotasie ongeldig slegs die vorige verslag, nie die beleidstoestand van die databasis nie.
Toets die skandeerder die nuwe Supabase publiseerbare-sleutel-model (<code>sb_publishable_*</code>)?
Ja. Die detektor erken beide oudere anon-JWT's en die nuwer sb_publishable_*-sleutels en behandel hulle identies — beide is bedoel om publiek te wees en albei laat RLS as die enigste verdedigingslinie.
Volgende stappe
Voer 'n gratis FixVibe-skandering teen jou produksie-URL uit — die baas.supabase-rls-toets is geaktiveer op elke plan, insluitend die gratis vlak. Vir 'n dieper lees oor wat anders uit 'n Supabase-projek kan lek, sien Supabase-diens-rol-sleutel blootgestel in JavaScript en Supabase-stoorbak-sekuriteitskontrolelys. Vir die sambreel-oorsig oor alle BaaS-verskaffers, lees BaaS-wankonfigurasieskandeerder.
