Sicurezza · 6 min di lettura ·
Supabase RLS: cos'è e perché i dati della tua app sono esposti
Supabase RLS spiegata semplice: perché senza regole chiunque può leggere o modificare i dati della tua app Lovable o Bolt, e come verificarlo e sistemarlo.

Se ti stai chiedendo cos'è la RLS di Supabase o se la tua app fatta con Lovable o Bolt è davvero sicura, la risposta breve è questa. La RLS (Row Level Security, sicurezza a livello di riga) è l'insieme di regole che decide chi può leggere e modificare ogni dato del database. Se è spenta o scritta male, chiunque può leggere, modificare o cancellare i dati della tua app, anche senza fare login. Qui sotto vediamo perché succede, come verificarlo e come sistemarlo.
Perché la chiave pubblica di Supabase non ti protegge
Molte app create con l'AI usano Supabase come database. Il database è l'archivio dove finiscono utenti, ordini, messaggi. In queste app il frontend, cioè la parte che gira nel browser del visitatore, parla direttamente con il database attraverso le API di Supabase.
Per farlo usa due informazioni: l'indirizzo del progetto e la chiave pubblica (chiamata anon o publishable). Entrambe sono nel codice del sito, quindi chiunque può leggerle. Non è un errore: Supabase è progettato così.
Pensa a un condominio. L'indirizzo e il citofono sono pubblici, chiunque può suonare. La RLS è il portiere che decide chi può salire e in quale appartamento. Se il portiere non c'è, il citofono apre a tutti.
Cos'è la RLS di Supabase, in pratica
Ogni tabella è fatta di righe: un profilo, un ordine, una prenotazione. La RLS permette di scrivere delle regole, chiamate policy, che dicono per ogni operazione chi può toccare quali righe.
Una policy tipica dice: «ogni utente può vedere solo il proprio profilo». In SQL, il linguaggio dei database, si scrive così:
alter table profiles enable row level security;
create policy "Ogni utente vede solo il proprio profilo"
on profiles for select
to authenticated
using ( (select auth.uid()) = user_id );
La prima riga accende la RLS sulla tabella. La seconda crea la regola: solo gli utenti che hanno fatto login (authenticated) possono leggere (select), e solo le righe in cui la colonna user_id corrisponde al loro identificativo (auth.uid()). Se nessuno ha fatto login, auth.uid() è vuoto e la regola non lascia passare nulla.
Le policy vanno pensate per ogni operazione: lettura (select), inserimento (insert), modifica (update) e cancellazione (delete). Proteggere la lettura e lasciare aperta la cancellazione non serve a molto.
Le situazioni che espongono i dati
Queste sono le configurazioni più comuni che espongono i dati nelle app create con intelligenza artificiale.
| Situazione | Cosa succede | Come riconoscerla |
|---|---|---|
| RLS disattivata su una tabella | Chiunque può leggere, modificare e cancellare tutte le righe | Il Security Advisor di Supabase la segnala come errore |
RLS attiva con policy using (true) | Sembra protetta, ma la regola lascia passare tutti | Leggendo le policy trovi true come condizione |
| Solo la lettura è protetta | I dati non si vedono, ma si possono modificare o cancellare | Mancano policy per update o delete, oppure sono troppo larghe |
| Regole basate sui metadati dell'utente | L'utente può modificarli da solo e darsi più permessi | Le policy usano user_metadata |
| Viste (view) sul database | Una vista può ignorare la RLS delle tabelle da cui legge | Il Security Advisor segnala viste con privilegi elevati |
| Chiave service_role o secret nel frontend | La RLS viene saltata del tutto | La chiave compare nei file del sito |
| File caricati in uno spazio pubblico | Documenti e foto sono raggiungibili da chiunque abbia il link | Lo spazio di archiviazione (bucket) è impostato come pubblico |
L'ultima riga merita attenzione: anche i file caricati dagli utenti, come documenti d'identità o fatture, hanno le loro regole di accesso, separate da quelle delle tabelle.
Perché succede con le app create con l'AI
Il motivo più comune è semplice. Quando la RLS è attiva e manca una regola, l'app smette di funzionare: le liste restano vuote e gli inserimenti falliscono con un errore come new row violates row-level security policy for table "orders". Chiedendo all'AI di «sistemare l'errore», la correzione più rapida è spegnere la RLS o scrivere una regola che lascia passare tutti. L'errore sparisce, la protezione pure.
Altre cause frequenti:
- tabelle create con comandi SQL in cui la RLS non è stata accesa;
- nuove tabelle aggiunte in un secondo momento, senza regole;
- la chiave di servizio usata nel browser perché «con quella funziona», un errore che trattiamo nella guida sulle chiavi API esposte nel frontend;
- un ruolo «admin» deciso da un campo che l'utente può modificare.
Se stai inseguendo messaggi come permission denied for table, trovi le spiegazioni nell'articolo sugli errori Supabase più comuni.
Come capire se i tuoi dati sono esposti
Puoi fare una prima verifica senza scrivere codice.
- Apri il Security Advisor di Supabase. Nella dashboard del progetto c'è una sezione dedicata ai controlli di sicurezza. Segnala, tra le altre cose, le tabelle pubbliche senza RLS, le policy che usano i metadati dell'utente e le viste che ignorano le regole.
- Usa lo scanner della piattaforma. Lovable, per esempio, esegue un controllo di sicurezza prima della pubblicazione e ha una vista dedicata ai problemi trovati. È utile, ma non conosce le regole della tua app: una policy che lascia passare tutti potrebbe non essere segnalata come problema.
- Leggi le policy, tabella per tabella. Per ognuna chiediti: chi deve poter leggere? Chi deve poter scrivere? Le regole che vedi corrispondono a quello che hai in mente?
- Fai una prova pratica con due account. Crea due utenti di prova. Con il primo crea dei dati, poi entra con il secondo e prova a vederli, per esempio cambiando l'identificativo nell'indirizzo della pagina. Ripeti la prova senza fare login, da una finestra in incognito.
Fai queste prove solo sulla tua app, mai su quelle di altri.
Come sistemare la RLS, passo per passo
Prima di toccare le regole, fai un backup del database: se qualcosa va storto, puoi tornare indietro. Ne parliamo nella guida sul backup del database.
- Fai una mappa delle tabelle. Per ognuna scrivi chi può leggere e chi può scrivere. Per esempio: «profili: ognuno legge e modifica il proprio», «prodotti: tutti leggono, solo l'admin modifica», «ordini: ognuno vede i propri, nessuno cancella».
- Accendi la RLS su tutte le tabelle pubbliche. Anche su quelle che sembrano innocue.
- Scrivi una policy per ogni operazione necessaria. Parti dal principio che tutto è chiuso e apri solo ciò che serve.
- Gestisci l'admin in modo sicuro. Il ruolo va salvato in una tabella che gli utenti non possono modificare, non nei metadati del profilo. Approfondiamo nella guida su ruoli e permessi admin.
- Controlla viste e file. Le viste devono rispettare le regole delle tabelle; gli spazi per i file privati non devono essere pubblici.
- Ripeti le prove con due account e senza login. Poi riapri il Security Advisor e verifica che non ci siano più errori.
Se usi un assistente AI, sii esplicito nella richiesta:
Attiva la RLS su tutte le tabelle dello schema public.
Per ogni tabella crea policy separate per select, insert,
update e delete secondo questa mappa: [incolla la tua mappa].
Non usare mai using (true) per dati degli utenti
e non disattivare la RLS per risolvere errori.
Poi rileggi le policy generate: devono corrispondere alla tua mappa, riga per riga.
Quando conviene farti aiutare
Se la tua app è ancora un prototipo con dati finti, puoi imparare molto sistemando la RLS da solo. Conviene chiedere aiuto se ci sono già utenti reali, se l'app gestisce dati personali, pagamenti o documenti, oppure se ogni regola che aggiungi rompe qualcos'altro.
Di solito facciamo una revisione completa delle tabelle, delle policy, delle viste e dei file, e proviamo l'app come la proverebbe un malintenzionato. Se vuoi capire a che punto sei, prenota una call gratuita e ne parliamo insieme.


