TIPS 24 · PORTA

Il tuo database risponde a tutti?

Il test di due minuti per capire se il database della tua app risponde anche a chi non ha fatto login, e il prompt che lo chiude. Solo sulla tua app.

Cos'è e perché conta

Molte app fatte con Claude Code usano un backend già pronto, tipo Supabase o Firebase. È comodo: l'app parla direttamente con il database, dal browser o dal telefono, senza un server tuo in mezzo.

Per farlo, l'app si porta dietro due cose: l'indirizzo del progetto e una chiave pubblica. Chiunque apra la tua app le può vedere, basta guardare le richieste nel browser. Ed è giusto così: quella chiave è fatta per stare lì. Non è una password, dice solo «questa richiesta arriva dalla mia app».

Il punto è cosa c'è dietro la porta. A decidere chi può leggere cosa non è la chiave: sono le regole sul database. Su Supabase si chiamano Row Level Security (sicurezza a livello di riga), su Firebase regole di sicurezza. In parole semplici: per ogni tabella scrivi chi può leggere, aggiungere, modificare e cancellare quali righe. Per esempio: «ogni utente vede solo i suoi ordini».

Se quelle regole mancano, o sono scritte troppo larghe, la chiave pubblica apre tutto. Chi copia indirizzo e chiave dal browser può leggere le tabelle: email, nomi, messaggi, tutto quello che ci hai messo. A volte anche modificarle. Non serve essere un hacker: basta una riga nel terminale.

Claude crea le tabelle e l'app funziona, perché a te, da loggato, i dati arrivano. Che arrivino anche a chi non ha nessun account, usando l'app non lo vedi. Lo vedi solo se lo provi.

Prima di tutto: solo sulla tua app

Questo test lo fai sul tuo progetto, con i tuoi dati o con utenti di prova. Mai su app o database di altri, nemmeno «solo per vedere»: entrare in un sistema senza permesso, in Italia come in molti altri paesi, può essere un reato. Se pensi che l'app di qualcun altro sia aperta, non provarla: scrivi a chi la gestisce.

1. Il test, in due minuti

Tre parti: la prima trova la chiave, la seconda guarda cosa vede chi non ha fatto login, la terza se un utente legge i dati di un altro. Le descrivo su Supabase; per Firebase guarda più sotto.

a. Trova la chiave

  1. Apri la tua app nel browser, senza fare login.
  2. Tasto destro > Ispeziona > scheda Rete (Network), poi ricarica la pagina.
  3. Cerca le richieste al database. Su Supabase sono indirizzi che finiscono in .supabase.co.
  4. Clicca una richiesta: lì vedi l'indirizzo del progetto e la chiave pubblica (publishable o anon).

Se non trovi richieste al database, vai in una pagina che carica dati e guarda di nuovo.

b. Prova a leggere senza login

Senza login, apri un terminale e lancia questa riga. Metti il tuo progetto, la tua chiave pubblica e il nome di una tua tabella:

La riga
curl "https://TUO-PROGETTO.supabase.co/rest/v1/NOME_TABELLA?select=*" -H "apikey: CHIAVE_PUBBLICA"

Se tornano righe di utenti, la porta è aperta. Se torna una lista vuota, [], o un errore di permesso, quella tabella non risponde a chi passa. Due attenzioni: controlla che nella tabella ci siano davvero dati, se no una lista vuota non ti dice niente. E ripetilo per ogni tabella, non solo per una.

c. Prova come utente A

Crea due utenti di prova, A e B, e fai salvare a ciascuno qualcosa: un profilo, una nota, un ordine. Poi entra come A e copia il suo token di accesso: lo trovi nella scheda Rete, nell'header Authorization delle richieste fatte dopo il login. Quindi lancia:

La riga
curl "https://TUO-PROGETTO.supabase.co/rest/v1/NOME_TABELLA?select=*" -H "apikey: CHIAVE_PUBBLICA" -H "Authorization: Bearer TOKEN_DI_A"

Le due intestazioni hanno ruoli diversi. La chiave pubblica va sempre in apikey. Authorization: Bearer porta solo il token di accesso di un utente che ha fatto login, mai la chiave pubblica e mai quella segreta. Per questo la prima riga ha solo apikey: lì non c'è nessun utente.

Se tra le righe ci sono quelle di B, A legge B. È il buco più facile da non notare: la porta è chiusa a chi non ha fatto login, ma una volta dentro ognuno vede tutto. Il token di A trattalo come una password: con quello sei A. Usalo solo per il test e non incollarlo da nessuna parte.

Se non vuoi farlo a mano

Chiedilo a Claude, dentro il tuo progetto. Fa lui le richieste al posto tuo:

Il prompt
Fai tu il test: con la chiave pubblica e senza login prova a leggere ogni tabella; poi con due utenti di prova controlla se A vede i dati di B. Dimmi tabella per tabella cosa è aperto. Non modificare niente.

Se Claude Code ti chiede il permesso per lanciare un comando, leggi cosa sta per fare prima di dire sì. «Non modificare niente» serve proprio a questo: il test legge, non scrive.

2. Il prompt che lo sistema

Quando sai cosa è aperto, chiudi. Questo è il prompt che uso io:

Il prompt
Ogni utente vede solo le sue righe. Attiva la Row Level Security su ogni tabella e scrivi le regole: lettura, inserimento, modifica e cancellazione solo sulle righe dell'utente loggato. Le tabelle davvero pubbliche (es. un catalogo) solo in lettura. Controlla anche le viste, le funzioni RPC e i bucket di Storage. Elencami ogni cosa con la regola che hai messo, poi rifai il test e mostrami che A non vede più B.

Le parole sono scelte. «Lettura, inserimento, modifica e cancellazione» perché su Supabase le regole si scrivono per ogni operazione: se chiudi solo la lettura, qualcuno può ancora scrivere o cancellare. «Le viste, le funzioni RPC e i bucket di Storage» perché i dati non escono solo dalle tabelle. Su Supabase una vista, di base, salta le regole delle tabelle che legge; una funzione può essere scritta in modo da saltarle; i file caricati hanno regole tutte loro. E «rifai il test» perché una regola la verifichi provandola, non leggendola.

3. Due cose da sapere

Meglio una porta chiusa

Su Supabase, con la Row Level Security attiva e nessuna regola scritta, dalla chiave pubblica non passa niente: meglio una porta chiusa che una aperta. Poi apri solo quello che serve. Se dopo il fix una schermata smette di caricare dati, non spegnere la sicurezza: manca una regola. Chiedi a Claude di aggiungere quella, e basta.

Le due chiavi

  • La chiave pubblica (publishable, o anon nei progetti più vecchi) può stare nell'app e nel browser. Da sola apre solo quello che le regole permettono.
  • La chiave segreta (secret o service_role) salta tutte le regole: solo sul server, mai nell'app, mai su GitHub.

Se la chiave segreta è finita nell'app o in un repository, considerala bruciata. Creane una nuova nel pannello di Supabase, mettila al posto della vecchia ovunque serva, e solo dopo elimina o disattiva quella vecchia. Toglierla dal codice non basta: resta nella cronologia e in chi l'ha già vista.

Il prompt
Cerca nel codice dell'app, e in tutto quello che finisce nel browser o nell'app pubblicata, se c'è la chiave segreta di Supabase (secret o service_role). Controlla anche la cronologia di git. Dimmi dove la trovi. Non modificare niente.

Se usi Firebase

Stesso concetto, lì si chiamano regole di sicurezza. Anche su Firebase la chiave dell'app non è un segreto: serve a riconoscere il progetto. A proteggere i dati sono le regole.

La regola da cercare è quella che lascia passare tutti, tipo allow read, write: if true. La documentazione di Firebase dice di non usarla mai in produzione. Al suo posto servono regole che controllano chi ha fatto login e di chi è il documento.

Il prompt
Leggi le regole di sicurezza di Firebase del mio progetto. Dimmi quali collezioni può leggere o scrivere chi non ha fatto login, e se un utente può leggere i documenti di un altro. Poi proponimi regole in cui ogni utente vede e modifica solo i suoi dati. Non pubblicare niente finché non te lo dico.

Gli errori più comuni

  • Fare il test su una sola tabella. Ogni tabella ha le sue regole: provale tutte.
  • Chiudere solo la lettura. Scrivi le regole anche per inserimento, modifica e cancellazione.
  • Chiudere le tabelle e dimenticare viste, funzioni e file. Controlla anche quelli, con lo stesso test.
  • Una regola che lascia leggere tutto a chiunque abbia fatto login. Il controllo giusto è su chi possiede la riga, non sul fatto di essere loggati.
  • Spegnere la sicurezza quando una schermata smette di funzionare. Aggiungi la regola che manca invece di riaprire tutto.
  • Mettere la chiave segreta nell'app o nel repository. Usala solo sul server e, se è uscita, sostituiscila.

Checklist

  • Ho fatto il test senza login su ogni tabella.
  • Con due utenti di prova, A non vede i dati di B.
  • Ogni tabella ha regole per lettura, inserimento, modifica e cancellazione.
  • Ho controllato anche viste, funzioni RPC e bucket di Storage.
  • Le tabelle pubbliche sono solo in lettura.
  • La chiave segreta sta solo sul server.
  • Ho rifatto il test dopo il fix.

Domande frequenti

Posso fare questo test sull'app di un altro, per curiosità?

No. Fallo solo sulla tua app. Leggere i dati di un sistema senza permesso può essere un reato, anche se la porta è aperta. Se sospetti un problema, avvisa chi gestisce l'app.

Dopo il fix l'app non carica più alcuni dati. Cosa ho sbagliato?

Probabilmente niente: la porta adesso è chiusa e manca una regola per quel caso. Di' a Claude quale schermata non carica e chiedigli la regola più stretta che basta, poi rifai il test con A e B.

Lo devo rifare ogni tanto?

Ogni volta che aggiungi una tabella o cambi chi può vedere cosa. Le regole valgono tabella per tabella, e una tabella nuova può nascere senza.

← Tutte le guide