Basi della sicurezza
Come ruotare una chiave service_role Supabase trapelata
Supabase dice di chiudere prima la falla. Altre guide dicono di ruotare subito. Quale sia giusto dipende da dove è finita la tua chiave service_role.

In breve
- Se la tua chiave service_role di Supabase è nel JavaScript che un browser scarica, ruotala prima di sistemare qualsiasi altra cosa. La copia già in circolazione non scade.
- Se è arrivata solo a un repository privato o a un log, chiudi prima la sorgente, altrimenti la chiave nuova segue la vecchia al deploy successivo.
- Una vecchia chiave service_role non si può ruotare affatto. Invalidarla significa creare le nuove chiavi sb_secret_, spostarci sopra la tua app e disattivare la vecchia coppia con un interruttore che le riguarda entrambe.
Qualcuno ti ha detto che la tua chiave service_role di Supabase si trova nella
tua app, dove chiunque può leggerla. Prima di cambiare qualsiasi cosa, assicurati
che sia davvero quella la chiave che hanno trovato:
la nostra scansione gratuita legge il tuo sito in produzione come lo
leggerebbe uno sconosciuto e ti dice quale chiave Supabase vede lì davvero. Senza
account e senza installare nulla.
Il consiglio che segue una scoperta del genere è quasi sempre una parola sola: ruotala. Poi vai a cercare come si fa, e le fonti si contraddicono. La documentazione di Supabase apre la sua guida alla rotazione dicendoti di correggere la causa della falla prima di iniziare. Una mezza dozzina di guide di terze parti ti dice di ruotare subito e fare domande dopo.
Ecco la parte che nessuna delle due scrive: hanno ragione entrambe, in situazioni diverse, e la domanda che le separa è dove sia finita la chiave.
Una cosa da mettere in chiaro prima di tutto. Cancellare la chiave dal tuo codice toglie la tua copia dal mazzo. Ruotarla cambia la serratura. Solo la seconda raggiunge le copie che altri hanno già.
È davvero la chiave service_role?
In un progetto recente rispondono i primi caratteri. sb_secret_ all'inizio è
quella segreta. sb_publishable_ è la chiave che deve stare nella tua app, e
trovarla lì non è affatto una scoperta.
Accertatene prima di fare qualcosa di drastico, perché la chiave che si trova in un'app fatta in vibe coding è di solito quella che ci deve stare.
I progetti più vecchi rilasciano un'altra coppia, anon e service_role, e le
due si assomigliano moltissimo: stesso formato, stessa lunghezza, nessun prefisso
da leggere. La sezione centrale di una di quelle chiavi non è cifrata affatto. Si
decodifica in qualche riga di testo semplice, e una di quelle righe indica il
ruolo.
Quali chiavi API sono sicure nel frontend
percorre entrambi i controlli.
Il motivo per esserne sicuri è che il caso è più raro di quanto suggeriscano gli
avvertimenti. Abbiamo scansionato 30.998 app in vibe coding ad agosto 2026 e
abbiamo trovato una chiave service_role pubblicata in 3 di esse. Una chiave API
di Google, di solito innocua e spesso limitata a un dominio, è comparsa in 1.142.
Il conteggio completo è qui.
Ruotare prima o chiudere prima la falla?
Dipende dal fatto che la chiave sia già pubblica, e la linea tra i due casi è netta.
Se la chiave è nel JavaScript che i tuoi visitatori scaricano, adesso è pubblica. Chiunque abbia caricato il tuo sito mentre era attiva ne ha una copia, e ce l'ha anche ogni crawler automatico che stava cercando esattamente quella stringa. Niente di quello che cambi nel tuo codice raggiunge quelle copie. Prima ruota, poi chiudi la sorgente.
Se è arrivata solo a un repository privato, a un file di log, a una variabile di CI o a una chat, l'esposizione è limitata. Se qui ruoti per prima cosa, lo farai due volte, perché il deploy successivo rimette fuori il valore vecchio da qualunque cosa lo producesse e la chiave nuova segue la vecchia. Chiudi la sorgente, poi ruota.
La guida di Supabase è scritta per il secondo caso. Le guide urgenti sono scritte per il primo. Se stai leggendo questo perché uno scanner ha trovato la chiave sul tuo URL in produzione, sei nel primo caso.
Come ruotare una chiave segreta di Supabase
Se il tuo progetto ha chiavi sb_secret_, è una faccenda da pannello e senza
interruzione di servizio.
Un progetto può tenere più di una chiave segreta alla volta, ognuna con il suo nome, ed è questo che rende l'operazione sicura: aggiungi la nuova prima di togliere la vecchia, quindi nel mezzo non c'è niente di rotto.
- Apri il progetto, vai su Settings → API Keys e crea una nuova chiave segreta.
- Mettila ovunque si usasse la vecchia, e dovrebbe essere tutto su un server: edge function, webhook, job pianificati, un backend tuo. Dove stanno quei valori se non hai mai aperto quella pagina.
- Fai il deploy, poi passa in rassegna le parti della tua app che leggono e scrivono dati. Una chiave segreta sbagliata fallisce in modo rumoroso e immediato, che è il caso buono.
- Solo allora cancella la chiave compromessa.
Il passo 4 è permanente. Supabase cancella una chiave segreta sul serio: nessun annulla, nessuna riattivazione, nessuna copia parcheggiata che tu possa recuperare. Per questo va per ultimo.
Cancellare una chiave segreta non fa uscire i tuoi utenti. Una chiave API dice quale applicazione sta interrogando il tuo database, e il token di sessione di un visitatore dice quale utente è. Il secondo viene verificato contro la chiave di firma del progetto, ed è un valore separato che non hai toccato.
Perché una vecchia chiave service_role di Supabase non si può ruotare
Perché non esiste un pulsante per farlo. La nota di troubleshooting di Supabase
dice che la rotazione diretta dei vecchi segreti anon, service_role e JWT non
è più supportata, e ti rimanda alle chiavi nuove.
Invalidare una vecchia chiave service_role trapelata è quindi una migrazione e
non una rotazione:
- Crea le chiavi nuove. Questo aggiunge
sb_publishable_esb_secret_accanto alla vecchia coppia. I due sistemi funzionano insieme e non si rompe niente. - Sposta il frontend sulla chiave pubblicabile. In Lovable o Bolt di solito è un valore nelle impostazioni del progetto e non una riga di codice.
- Sposta ogni uso lato server sulla chiave segreta.
- Disattiva le vecchie chiavi nelle impostazioni del progetto.
Il passo 4 è un solo interruttore e riguarda entrambe le vecchie chiavi. anon e
service_role sono JWT firmati con lo stesso segreto, quindi l'interruttore che
revoca l'una revoca anche l'altra, e un frontend che porta ancora la vecchia
chiave anon smette di funzionare nel momento in cui lo premi. Per questo il
passo 2 viene prima.
La disattivazione è reversibile, ed è l'unica buona notizia di questa sezione: se qualcosa che avevi dimenticato usa ancora una vecchia chiave, puoi riaccenderle mentre la sistemi. Cosa comporta la migrazione lo racconta più per esteso.
Da dove è trapelata la chiave, e come chiudere
Tre cause spiegano quasi tutto, e tutte e tre stanno dentro il tuo progetto.
Un prefisso VITE_ o NEXT_PUBLIC_. Non sono un'impostazione di sicurezza
che qualcuno ha dimenticato di attivare. Sono un'istruzione per la build: metti
questo valore nel bundle. Una variabile chiamata
VITE_SUPABASE_SERVICE_ROLE_KEY è stata compilata nel tuo JavaScript di
proposito, da uno strumento che ha fatto esattamente quello che gli era stato
detto.
Un valore incollato dritto in un componente. Nessun prefisso di mezzo e
nessun file .env, solo la chiave posata in una riga di codice perché era il
modo più veloce di far restituire qualcosa a una query.
Lavoro che sta su un server. Cancellare un account, scrivere in una tabella in cui i tuoi utenti non possono scrivere, leggere righe di tutti quanti. Alla chiave si è ricorsi perché il browser non poteva fare quel lavoro, e la soluzione è spostare il lavoro: una edge function, una rotta serverless, qualsiasi cosa che i tuoi visitatori non scarichino.
Come faccio a sapere se qualcuno l'ha usata?
Di solito non puoi esserne certo. Quello che puoi fare è restringere la finestra e guardarci dentro.
La finestra si apre con il deploy che ha pubblicato la chiave per la prima volta e si chiude quando l'hai disattivata. Il tuo progetto Supabase tiene log sia per l'API sia per il database, ed è su quell'intervallo che vanno filtrati. Quello che cerchi sono letture e scritture che non sai spiegare: richieste a tabelle che la tua app non tocca mai, traffico in ore in cui nessuno la stava usando, cancellazioni che non ha fatto nessuno.
Poi controlla i dati stessi. Conteggi di righe rispetto a quello che ti aspetti, i tuoi stessi record di account, qualsiasi cosa con una marca temporale che si è mossa mentre nessuno lavorava. Un messaggio all'assistenza su dati cambiati da soli è il modo in cui la maggior parte di questi casi viene davvero scoperta, e arriva settimane dopo.
Una chiave service_role non raggiunge il tuo fornitore di pagamenti né il tuo
invio di email. Vale comunque la pena sapere se era l'unica chiave nel tuo
bundle, perché quelle che spendono soldi trapelano per la stessa strada:
cosa pubblicavano 30.998 app.
Controlla la tua app in produzione prima di darla per chiusa
Carica il sito in una finestra privata, apri il JavaScript che il browser ha scaricato e cercaci dentro il valore vecchio. Poi cerca quello nuovo, che lì non dovrebbe esserci nemmeno lui.
Due cose rendono utile questo controllo a mano. Una build può servire un bundle in cache ancora per un po' dopo il deploy, quindi il file che riceve un visitatore non è sempre quello che hai appena costruito. E una chiave può stare in più di un posto: un secondo punto di ingresso, un service worker, una vecchia build ancora servita da un percorso a cui nessuno rimanda.
La nostra scansione gratuita fa questa parte da fuori, sull'URL che i tuoi visitatori usano davvero, e decodifica una chiave Supabase quanto basta per leggerne il ruolo, quindi una chiave pubblicabile torna con una spunta. Ci mette una ventina di secondi e non richiede un account: scansiona la tua app.
Cosa fare adesso
Cosa fare
- Conferma prima la chiave.
sb_secret_davanti, oppure"role": "service_role"dentro una più vecchia. Una chiave pubblicabile nel tuo frontend non è una scoperta. - Se è nel bundle che i tuoi visitatori scaricano, ruotala prima di toccare il codice. Modificare la tua app non raggiunge le copie già in circolazione.
- Se è trapelata solo a un repository, a un log o a una chat, chiudi prima la sorgente, così il prossimo deploy non rimette subito fuori la chiave nuova.
- In un progetto recente: crea una seconda chiave segreta, spostaci sopra il codice del server, fai il deploy e poi cancella la vecchia. La cancellazione è definitiva.
- In un progetto vecchio non c'è un pulsante di rotazione. Crea le chiavi nuove, spostaci sopra frontend e server, poi disattiva la vecchia coppia con l'unico interruttore che le riguarda entrambe.
- Dopo, cerca dentro il tuo bundle in produzione. Una build in cache può servire il valore vecchio ancora per un po' dopo il deploy.
Una chiave service_role legge e scrive ogni riga del tuo database. La versione
peggiore di questa storia finisce con una tabella vuota, e se quelle righe
tornano dipende da
cosa stavi salvando prima che
succedesse tutto questo.
FAQ
Ruotare la chiave rompe la mia app in produzione?
No, se rispetti l'ordine. In un progetto con le chiavi nuove aggiungi una seconda chiave segreta, ci sposti sopra il codice del tuo server, fai il deploy e solo allora cancelli la vecchia, così non esiste mai un momento senza una chiave funzionante. In un progetto vecchio il rischio è un altro: disattivare la vecchia coppia disattiva anche la chiave anon che usa il tuo frontend, quindi la tua app si ferma se non è già passata alla chiave pubblicabile quando premi quell'interruttore.
Posso ruotare le vecchie chiavi anon e service_role?
No. La documentazione di troubleshooting di Supabase dice che la rotazione diretta dei vecchi segreti anon, service_role e JWT non è più supportata. Invalidare una vecchia chiave trapelata significa creare le nuove chiavi sb_publishable_ e sb_secret_, spostarci sopra la tua app e il codice del tuo server, e poi disattivare la vecchia coppia nelle impostazioni del progetto.
Devo cancellare la vecchia chiave o disattivarla?
Non puoi scegliere, perché i due sistemi di chiavi si comportano in modo diverso. Una chiave sb_secret_ recente viene cancellata, in modo permanente, senza alcun modo di recuperarla. La vecchia coppia si disattiva invece, e la disattivazione è reversibile: se qualcosa che avevi dimenticato usa ancora una vecchia chiave, puoi riaccenderle mentre la sistemi.
Come faccio a sapere se qualcuno l'ha usata?
Di solito non puoi esserne certo. Riducilo piuttosto a una finestra temporale: la chiave è stata utilizzabile dal deploy che l'ha pubblicata per la prima volta fino al momento in cui l'hai disattivata. Filtra i log dell'API e del database del tuo progetto Supabase su quell'intervallo e cerca letture e scritture che non sai spiegare, poi controlla i dati stessi: conteggi di righe e marche temporali che non corrispondono a nulla che tu abbia fatto.
Devo ruotare anche la chiave anon?
In un progetto vecchio non puoi scegliere: disattivare la vecchia coppia porta via entrambe le chiavi in una volta, quindi il tuo frontend ha bisogno della nuova chiave pubblicabile prima che tu prema l'interruttore. In un progetto recente la chiave pubblicabile è pensata per essere pubblica e non c'è motivo di toccarla. Quello che vale la pena controllare in entrambi i casi è Row Level Security, perché è l'unica cosa che sta tra una chiave pubblicabile e tutto il tuo database.