// docs / baas security / supabase rls scanner
Scanner RLS Supabase: trova tabelle cù sicurezza à livellu di riga mancante o rotta
A sicurezza à livellu di riga (RLS) hè a sola cosa chì stà trà i dati di i to clienti è internet quandu mandi una app supportata da Supabase. L'attrezzi di codifica IA generanu codice à forma di RLS chì compila, parte è perde dati in silenziu — tabelle create senza RLS attivatu, pulitiche chì leghjenu ma ùn ristringhjenu mai, predicati chì paragunanu una colonna cù ella stessa. St'articulu mostra ciò chì un scanner RLS Supabase pò pruvà da fora, e quattru forme di RLS rotta chì appariscenu in l'app vibe-coded, è cumu scansiunà u to propiu spiegamentu in menu d'un minutu.
Ciò chì una scansione RLS esterna pò pruvà
Una scansione RLS passiva gira contru à l'endpoint PostgREST chì Supabase espone à https://[project].supabase.co/rest/v1/. Adopra solu a chjave publishable anon — listessa chì u to navigatore adopra — è sonda metadata di lista di tabelle, letture anonime è scritture anonime. Ùn s'autentica mai cum'è un utente è ùn tocca mai privileghji di service-role. Qualcosa pò fà, un attaccante micca autenticatu in internet pò fà.
Da fora di a basa di dati, un scanner pò cunfirmà ciò chì seguita cù alta fiducia:
- RLS hè disattivatu nantu à una tabella. PostgREST torna righe per un
SELECTanonimu quandu RLS hè spentu o quandu una pulitica u permette. I dui casi sò un risultatu. - U rolu anonimu pò listà e tabelle. Un
GET /rest/v1/cù a chjave anon torna u schema OpenAPI per ogni tabella nantu à chì u roluanonhà qualunque privileghju. L'app generate da IA spessu cuncedanuUSAGEnantu à u schema èSELECTnantu à ogni tabella, ciò chì espone a carta sana di u schema ancu quandu RLS nega e letture vere. - U rolu anonimu pò inserà. Un
POSTdi sondaghju cù una supposizione di a forma di e colonne riesce s'è RLS ùn hà micca una puliticaINSERTchì u nega — ancu s'èSELECThè chjusu. - A chjave di service-role hè in u bundle di u navigatore. Vicinu à RLS: s'è un scanner trova
SUPABASE_SERVICE_ROLE_KEYo qualunque JWT cùrole: service_rolein u bundle JavaScript, RLS hè irrilevante — u titulare di quella chjave passa sopra ogni pulitica.
Ciò chì una scansione esterna ùn pò pruvà
Sia onestu nantu à i limiti di u scanner. Una scansione RLS esterna ùn pò leghje a to tabella pg_policies, i to schedarii di migrazione o u predicatu esattu di qualunque pulitica. Inferisce da u cumpurtamentu black-box, ciò chì vole dì ch'ella sgnalerà à volte un risultatu chì si svela esse datu publicu vulutu (una tabella di newsletter di marketing, un catalogu prudottu publicu). U raportu FixVibe i marca cum'è fiducia media quandu u scanner ùn pò micca disambiguà l'intenzione — rivedi u nome di a tabella è decidi.
E quattru forme di RLS rotta chì l'attrezzi IA producenu
Quandu punti Cursor, Claude Code, Lovable, o Bolt à Supabase, listessi quattru pattern di RLS rotta emergenu trà mille di app. Ognunu passa u type-check, compila è parte:
Forma 1: RLS mai attivatu
U modu di fallimentu più cumunu. A migrazione crea a tabella ma u sviluppatore (o l'attrezzu IA) si scorda ALTER TABLE ... ENABLE ROW LEVEL SECURITY. PostgREST serve cuntentu a tabella sana à chì abbia a chjave anon. Currezzione: ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY; ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;. FORCE ùn hè opzionale — senza ellu u patrone di a tabella (è ogni rolu cù pruprietà di tabella) passa sopra RLS.
ALTER TABLE public.[name] ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.[name] FORCE ROW LEVEL SECURITY;Forma 2: RLS attivatu, nessuna pulitica
Un fallimentu più sutile. RLS hè attivatu ma nesuna pulitica hè scritta. U difettu in PostgreSQL hè nega, dunque l'utenti autenticati ùn vedenu nunda — è u sviluppatore aghjusta USING (true) per fà funziunà l'app, ciò chì permette à tutti di leghje tuttu. Currezzione: scrivi una pulitica chì limita per auth.uid(): CREATE POLICY "select_own" ON public.[name] FOR SELECT USING (auth.uid() = user_id); è una pulitica INSERT/UPDATE/DELETE currispundente.
CREATE POLICY "select_own"
ON public.[name]
FOR SELECT
USING (auth.uid() = user_id);Forma 3: pulitica paragona colonna cù ella stessa
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: pulitica nantu à SELECT ma micca nantu à INSERT/UPDATE
U sviluppatore chjude e letture ma si scorda e scritture. E pulitiche RLS sò per-cumandu. FOR SELECT prutege solu e letture; un cliente anonimu pò sempre INSERT s'è nesuna pulitica u nega. Currezzione: scrivi una pulitica per cumandu, o adopra FOR ALL cù clausule USING è WITH CHECK esplicite.
Cumu funziona u scanner RLS Supabase di FixVibe
U check baas.supabase-rls gira in trè tappe, ognuna cù livelli di fiducia espliciti:
- Tappa 1 — fingerprint. U scanner crawla l'app spiegata, analizza u so bundle JavaScript è estrae l'URL di u prughjettu Supabase è a chjave anon da a cunfigurazione runtime. Nisun DNS guessing, nisun brute force — leghje ciò chì leghje u navigatore.
- Tappa 2 — scuperta di schema. Un sulu
GET /rest/v1/cù a chjave anon torna u schema OpenAPI per ogni tabella chì u rolu anon pò vede. U scanner registra i nomi di e tabelle ma ùn leghje micca dati di righe in sta tappa. - Tappa 3 — sondaghji di lettura è scrittura. Per ogni tabella scuperta, u scanner emette un
SELECTanonimu cùlimit=1. S'è ritornanu righe, RLS hè permissivu. U scanner si ferma quì — ùn enumera righe, ùn pagina, ùn modifica dati. I sondaghji INSERT sò gattati daretu à verifica di pruprietà di duminiu è opt-in esplicitu; ùn parteranu mai contru à miri micca verificati.
Ogni risultatu vene cù l'URL esatta di a richiesta, u statutu di a risposta, a forma di a risposta (solu testa) è u nome di a tabella. U suggerimentu di currezzione IA in fondu à u risultatu hè un bloccu SQL prontu à incolla chì lampi in l'editore SQL di Supabase.
Ciò chì fà quandu u scanner trova qualcosa
Ogni risultatu RLS hè una emergenza in runtime. L'endpoint PostgREST pubblichi sò scansiunati da l'attaccanti in minuti. A sequenza di remediazione hè meccanica:
- Auditeghja ogni tabella. Lampa
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';in l'editore SQL di Supabase. Ogni riga cùrowsecurity = falsehè un prublema. - Attiveghja RLS nantu à ogni tabella pubblica. Per difettu, applica
ENABLE ROW LEVEL SECURITYèFORCE ROW LEVEL SECURITYnantu à ogni tabella creata — fànne un mudellu di migrazione. - Scrivi pulitiche cumandu per cumandu. Ùn aduprà
FOR ALL USING (true). Scrivi pulitiche esplicite per SELECT, INSERT, UPDATE, DELETE — ognuna limitata àauth.uid()o à una colonna org-id daauth.jwt(). - Verifica cù un secondu cunto. Iscriviti cum'è un utente sfarente, prova à leghje i registri di un altru utente via l'API REST direttamente. S'è a risposta hè
200, a pulitica hè rotta. - Riscaneghja. Dopu avè applicatu a currezzione, lampa di novu una scansione FixVibe contru à listessu URL. U risultatu
baas.supabase-rlsdeve sparisce.
-- 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;Cumu si paragona à altri scanner
A maiò parte di l'attrezzi DAST generichi (Burp Suite, OWASP ZAP, Nessus) ùn sanu ciò chì hè PostgREST. Anu da crawlà a to app, ignurà u percorsu /rest/v1/, è raportà nantu à e pagine HTML chì capiscenu. Snyk è Semgrep sò attrezzi d'analisi statica — trovanu schedarii di migrazione in u to repo cù chjamate RLS mancante, ma ùn ponu pruvà chì a basa di dati spiegata hè mal cunfigurata. FixVibe stà in u spaziu: passivu, BaaS-cunsciu, focalizatu nantu à ciò chì un attaccante micca autenticatu pò pruvà da l'URL pubblicu.
Dumande frequenti
U scanner leghjerà o mudificherà i mio dati?
Nò. E scansioni passive emettenu al massimu un SELECT ... limit=1 per tabella scuperta per cunfirmà s'è RLS permette letture anonime. U scanner registra a forma di a risposta, micca u cuntenutu di e righe. I sondaghji INSERT, UPDATE è DELETE sò gattati daretu à verifica di pruprietà di duminiu è ùn parteranu mai contru à miri micca verificati.
Funziuna s'è u mio prughjettu Supabase hè in pausa o nantu à un duminiu persunalizatu?
I prughjetti in pausa tornanu 503 in ogni richiesta — u scanner riporta u prughjettu cum'è inghjuntu. I duminii persunalizati funziuneghjanu finu chì l'app spiegata carca sempre l'SDK cliente Supabase in u navigatore; u scanner estrae l'URL di u prughjettu da u bundle in ogni casu.
Ciò chì succede s'è a mio chjave anon hè ruttata o a mio chjave publishable cambia?
Rilampa a scansione. U scanner ri-estrae a chjave da u bundle currente in ogni esecuzione. A rotazione invalideghja solu u raportu precedente, micca u statu di pulitica di a basa di dati.
U scanner cuntrolla u novu mudellu di chjave publishable Supabase (<code>sb_publishable_*</code>)?
Iè. U rilevatore ricunnosce sia i JWT anon legacy sia e più recenti chjavi sb_publishable_* è e tratta identicamente — tramendue sò destinate à esse publiche è tramendue lascianu RLS cum'è a sola linea di difesa.
Prussimi passi
Lampa una scansione FixVibe gratisa contru à u to URL di produzzione — u check baas.supabase-rls hè attivatu in ogni pianu cumpresu u pianu gratisi. Per una lettura più prufonda nantu à ciò chì altru pò perde da un prughjettu Supabase, vedi Chjave di service-role Supabase esposta in JavaScript è Lista di cuntrollu di sicurezza di bucket Supabase Storage. Per a vista d'imbrelli trà tutti i fornitori BaaS, leghji Scanner di sbagli di cunfigurazione BaaS.
