Vai al contenuto

Basi della sicurezza

Chiave API esposta nel frontend: cosa spediscono 30.998 app

Una chiave API esposta nel tuo frontend è quasi sempre una chiave di Google Maps. Abbiamo scansionato 30.998 app vibe-coded e contato cosa esce davvero.

Vlad Tkachenko8 min di lettura
Una pagina di codice di un’app con otto valori a forma di chiave evidenziati, quasi tutti ordinari e uno disegnato in rosso.

In breve

  • Una chiave API esposta nel tuo frontend è quasi sempre del tipo innocuo. Abbiamo trovato una chiave degna di nota in 1.332 app su 30.998, e 1.080 di quelle portavano soltanto una chiave API Google.
  • La chiave service_role di Supabase, quella contro cui mette in guardia ogni tutorial, è comparsa in 3 app su 30.998. Una chiave segreta Stripe è comparsa anch’essa in 3.
  • Le chiavi che spendono denaro o leggono dati per la loro stessa forma sono comparse in 54 app. Una tabella Supabase aperta è comparsa in 2.096.

Qualcuno apre la tua app, preme F12 e ti dice che c’è una chiave API esposta nel tuo frontend. La parola usata di solito è «trapelata». Raramente ti dicono quale chiave sia, e i consigli che trovi dopo trattano tutte le chiavi come la stessa emergenza.

Non sono la stessa emergenza, e ora possiamo mettere dei numeri sulla distanza. Tra il 12 e il 14 agosto 2026 abbiamo eseguito nove controlli esterni su 30.998 app online costruite con Lovable, Bolt, v0, Replit e Base44, e letto il JavaScript che ciascuna consegna a un browser. Ecco cosa c’era dentro.

Una chiave API esposta nel frontend è davvero un problema?

Di solito no, e la forma di questo «di solito» è più sbilanciata di quanto ci aspettassimo.

Abbiamo trovato una chiave degna di nota in 1.332 delle 30.998 app. In 1.080 di esse l’unica cosa trovata era una chiave API Google, cioè proprio la credenziale che deve stare nella tua pagina. A proteggere quella è un’impostazione conservata dalla parte di Google, e nasconderla non ha mai fatto parte dell’accordo.

Le altre 29.666 app non consegnavano nulla che il nostro controllo dei segreti tratti come un problema. Quel numero ha bisogno di una precisazione per essere onesto: le chiavi pubblicabili ne sono escluse. Una chiave anon di Supabase o una chiave pk_ di Stripe appartiene al browser, quindi la segniamo come una cosa che hai fatto bene e non entra mai in questi conteggi.

Cosa abbiamo contato e cosa non siamo riusciti a contare

Abbiamo caricato ogni app come fa un visitatore, in un browser vero, e letto il JavaScript scaricato. Tutto ciò che segue è una forma trovata in quel codice.

Riconosciamo i formati di chiave che conosciamo. Stripe, OpenAI, Anthropic, AWS, Google e Supabase hanno prefissi identificabili, e un JWT Supabase dichiara il proprio ruolo in testo leggibile nella sezione centrale. Una credenziale in un formato che non riconosciamo non è in questi numeri, quindi leggili come un minimo.

Non abbiamo usato nessuna chiave trovata. Nemmeno una volta, su nessuna app. Abbiamo annotato il tipo e un indizio mascherato nella forma sk_live_…a1b2, e il valore reale non è stato scritto da nessuna parte.

Nessuna app viene nominata. Non qui, non nel set di dati, non in nulla di ciò che pubblichiamo.

Quasi tutte sono app pubblicate sul dominio di un builder. Il metodo completo, il campione e ogni cifra dietro questo articolo sono nel nostro rapporto di scansione, compreso ciò che non siamo riusciti a misurare.

Cosa spedivano davvero le 30.998 app

Una tabella, ordinata per quante volte abbiamo visto ciascuna cosa. Il controllo dei segreti si è concluso su tutte e 30.998 le app, quindi ogni conteggio qui sotto è su tutte.

Cosa abbiamo trovato nel codice del browserApp
Chiave API Google1.142
Un valore ad alta entropia accanto a un nome «secret» o «password»204
Chiave OpenAI33
Chiave di accesso AWS9
Chiave Anthropic5
Chiave service_role di Supabase3
Chiave segreta Stripe3
Chiave con restrizioni Stripe2

Le righe sommate superano 1.332 perché una singola app può portarne due. Ordina quelle stesse 1.332 app in gruppi che non si sovrappongono e il quadro diventa ancora più netto: 1.080 avevano una chiave Google e nient’altro, 198 avevano un valore ad alta entropia che può essere o non essere una credenziale vera, e 54 avevano una chiave che è un segreto autentico già per la sua forma.

Ogni app in cui abbiamo trovato una chiave, ordinata in tre gruppi che non si sovrappongono. La sezione rossa è quella di cui parlano gli avvertimenti.

Il secondo gruppo merita di essere descritto con cura. Un valore ad alta entropia messo accanto a una parola come secret o password può essere una credenziale viva, oppure un identificatore di sessione, un hash di build o un token pubblico con un nome sfortunato. Lo segnaliamo come qualcosa da guardare, e dall’esterno nessuno può dirti quale delle due cose sia.

Le 54 del terzo gruppo sono la cosa vera. Tutte tranne due sono uscite con voto D o F, perché un solo riscontro critico limita il voto a D per quanto bene l’app abbia fatto tutto il resto. Il gruppo singolo più grande al suo interno è la chiave OpenAI, a quota 33, e quella non ha nessuna impostazione che la renda sicura in un browser.

La chiave contro cui tutti mettono in guardia era la cosa più rara

Tre app. Tante sono quelle che spedivano una chiave service_role di Supabase, quella che passa oltre ogni regola di tabella che hai scritto. Una chiave segreta Stripe è comparsa anch’essa tre volte.

Mettilo accanto all’altra metà della stessa scansione. Fra le app scansionate, 8.429 nominavano un progetto Supabase, e i due riscontri stanno dentro quello stesso gruppo. Tre di esse spedivano la chiave service_role. In 2.096 di esse almeno una tabella ha risposto a una richiesta senza alcun accesso, e in 394 quella tabella portava un nome di persone: users, profiles, customers, orders.

Entrambi i conteggi vengono dalle stesse 8.429 app con Supabase. La riga in alto è il riscontro contro cui i proprietari vengono messi in guardia.

Le 2.096 sono un minimo. 4.749 delle 8.429 non hanno mai risposto al nostro controllo del database, per ragioni che dall’esterno non vediamo, e quelle sono registrate come sconosciute anziché come pulite. Le tre chiavi service_role sono un conteggio esatto, perché una chiave si legge da codice che ogni app consegna.

Perché gli avvertimenti puntano alla chiave sbagliata

Vediamo solo l’esterno di queste app, quindi non possiamo dirti perché. Ciò che possiamo mostrare è quale errore sopravvive.

Copiare la chiave Supabase sbagliata è davvero facile. In un progetto più vecchio, anon e service_role stanno una accanto all’altra nello stesso pannello della dashboard, hanno la stessa lunghezza e la stessa forma, e non si rompe nulla se prendi quella sbagliata. Eppure è successo solo tre volte su 30.998 app, perché nulla ti spinge in quella direzione. Incollare l’una o l’altra fa funzionare l’app.

La tabella aperta, invece, ha una forza dietro di sé. Row Level Security viene attivata, l’app smette di mostrare dati, viene scritta una policy che permette a chiunque per farla tornare a funzionare, e da quel momento la dashboard segnala la tabella come protetta. Attivarla non è la stessa cosa che essere protetti. La nostra scansione classifica quella tabella come riscontro critico in un giorno in cui la tua dashboard ti mostra l’interruttore attivo e una policy al suo posto.

Come trovare gratis una chiave API esposta nella tua app

Comincia a mano, perché costa cinque minuti e non richiede nulla da installare. Apri il tuo sito online, guarda il codice sorgente della pagina e cerca quattro stringhe: AIza per una chiave Google, sk_ per un segreto Stripe o di un fornitore di modelli, service_role per la chiave Supabase che ignora le tue regole, e eyJ per qualunque token Supabase. Tutto ciò che torna indietro è già nelle mani di ogni visitatore che hai.

Questo ti dà la pagina in sé. Ciò che sfugge è il JavaScript che la pagina carica dopo, ed è esattamente per questo che il nostro scanner apre un’app in un browser vero e legge i bundle invece dell’HTML. Cercare a mano non può nemmeno dirti se il token eyJ che hai trovato è la chiave anon o quella segreta, perché le due hanno la stessa lunghezza e la stessa forma.

La nostra scansione gratuita copre entrambe le cose. Carica la tua app in un browser vero, legge il codice che arriva davvero, decodifica ogni token Supabase e riporta il ruolo scritto al suo interno, così una chiave pubblicabile torna segnata come corretta invece di finire sepolta in un muro di rosso. Ottieni un voto, un punteggio e i conteggi a schermo in una ventina di secondi senza account. Dai un indirizzo email e ottieni anche l’elenco dettagliato, con una correzione scritta per il tuo builder che puoi incollare direttamente.

Tre cose che non farà, e sono le ragioni per cui è sicuro su un’app online: non accede mai, non scrive mai nulla e non conserva mai una chiave che trova. Un segreto esposto viene salvato come indizio mascherato tipo sk_live_…a1b2, e il valore reale viene scartato. Scansiona la tua app, oppure leggi prima cosa guarda ciascuno dei nove controlli.

Cosa fare, nell’ordine che i numeri suggeriscono

Cosa fare

  • Identifica la chiave prima di reagire. Il prefisso risponde per Stripe e per le chiavi Supabase recenti; su una chiave Supabase più vecchia decide il campo role dentro il token.
  • Se è una chiave Google, limitala invece di nasconderla. Restrizione Siti web, il tuo dominio, solo le API che usi, più un tetto di quota giornaliera. Gratis, circa cinque minuti, nessuna modifica al codice.
  • Se è una vera chiave segreta, ruotala per prima cosa. Cancellarla dal codice non chiude nulla, perché il vecchio valore resta nella tua cronologia delle versioni e nelle copie in cache del tuo sito.
  • Poi vai a leggere le regole delle tue tabelle, che è dove i numeri collocano l’esposizione reale. Comincia dalle tabelle che contengono persone.
  • Controlla fatturazione e log dopo qualunque esposizione di una chiave segreta. Ruotare ferma ciò che succede da adesso, e non dice nulla su ciò che è già successo.

Percorri l’intero elenco in una sola volta con la checklist di sicurezza in 10 minuti, che copre la chiave e le regole delle tabelle insieme alle altre cose da chiudere in un’app appena lanciata. E se è la metà sul database di questo articolo a preoccuparti, ha un censimento tutto suo: chi può leggere il tuo database Supabase.

FAQ

Come capisco se la mia chiave API è trapelata?

Apri il tuo sito online, guarda il codice sorgente della pagina e cerca le forme: AIza per una chiave Google, sk_ per un segreto Stripe o di un fornitore di modelli, e eyJ per un JWT Supabase. Tutto ciò che salta fuori è già nelle mani di ogni visitatore. La nostra scansione gratuita fa la stessa lettura dall’esterno e riporta ciò che riesce a vedere in una ventina di secondi, senza account per ottenere il voto.

Una chiave API scritta nel codice è sempre un problema di sicurezza?

No, e crederlo è esattamente ciò che insegna alle persone a ignorare l’avviso. Alcune chiavi sono pubblicate apposta: una chiave anon di Supabase, una chiave pk_ di Stripe e una chiave di configurazione web di Firebase sono tutte pensate per stare nel browser, e ciò che protegge i tuoi dati sono le regole dietro di esse. Una chiave segreta è il caso opposto e il suo posto è un server. Il prefisso ti dice quale delle due hai davanti.

Mi hanno detto che la mia chiave Supabase è esposta. È quella brutta?

Quasi certamente no. Le due chiavi Supabase si somigliano, quindi leggi il ruolo dentro il token o controlla il prefisso: anon e sb_publishable_ devono essere pubbliche, service_role e sb_secret_ no. Abbiamo trovato una chiave service_role in 3 app su 30.998, quindi le probabilità pendono nettamente verso quella innocua. Se invece è quella segreta, ruotala oggi stesso nella dashboard di Supabase.

Di cosa dovrei preoccuparmi invece?

Delle regole sulle tabelle del tuo database. Fra le app in cui siamo riusciti a completare quel controllo, più della metà aveva almeno una tabella che rispondeva a una richiesta senza alcun accesso, e in 394 di esse la tabella aperta portava un nome di persone: users, profiles, customers, orders. È molto più comune di qualsiasi chiave trapelata e molto più silenzioso, perché l’app funziona esattamente uguale in entrambi i casi.

Ho tolto la chiave dal mio codice. Adesso è chiusa?

Non da sola. Il vecchio valore esiste ancora nella tua cronologia delle versioni e in qualunque copia in cache della pagina, quindi chi l’ha già raccolto può continuare a usarlo. Ciò che chiude davvero la porta è ruotare la chiave nella dashboard del fornitore, ed è il primo passo, non l’ultimo. Dopodiché controlla fatturazione e log per un uso che non riesci a spiegarti.

Scritto da

Vlad Tkachenko

Fondatore di Reeve

Passo le giornate a guardare app costruite con Lovable, Bolt, v0, Cursor e Replit, e la breve lista di errori che vi ricompaiono di continuo.

Altro sull'autore

Da leggere dopo

Tutti gli articoli

Non sai come sta messa la tua app?

Esegui una scansione gratuita e ottieni un voto chiaro da A a F in una ventina di secondi. Senza account e senza carta.

Scansiona la tua app gratis

Controllo esterno automatizzato, non un audit completo. L'assenza di risultati non è una garanzia di sicurezza.