← Guide per stack

Firebase

Sicurezza per la tua app con Firebase

La sicurezza di Firebase dipende quasi del tutto dalle regole che scrivi. Con le regole in modalità test o troppo aperte, il tuo database è alla portata di chiunque. Controlla questo prima di aprire la tua app.

Rischi tipici con Firebase

Regole in modalità test

La modalità test permette lettura e scrittura a tutti. Molti lanciano senza cambiarla, lasciando il database completamente aperto.

Confondere la chiave pubblica con la sicurezza

La config di Firebase è pubblica per design; ciò che protegge i tuoi dati sono le regole, non nascondere quella chiave. Dare per scontato il contrario porta a dati esposti.

Altre chiavi nel frontend

Accanto alla config di Firebase spesso si infilano chiavi che sono davvero segrete (pagamenti, email, IA). Quelle non devono mai stare nel JavaScript del browser.

"Sicurezza in Firebase" sono due cose che conviene tenere separate. La prima è il modello di Firebase: il browser parla direttamente con il database e lo storage, quindi non c'è un server che filtra, e la protezione vive nelle regole, in App Check e nella configurazione del progetto. La seconda è ciò che Lovable, Bolt o Cursor fanno con Firebase quando generano codice, ed è da lì che arrivano quasi tutti i buchi. Questa guida spiega il modello, ripassa ciò che l'IA sbaglia, ti lascia un firebase.json e delle regole base da incollare, un prompt di revisione e la verifica dall'esterno. I dieci errori di regole più comuni, con la regola sbagliata e quella giusta, sono in gli errori di sicurezza più comuni in Firebase.

Parte 1: come funziona la sicurezza in Firebase

Il client parla con i servizi, non con il tuo server

In una tipica app Firebase non c'è un backend tuo: l'SDK del browser legge e scrive direttamente su Firestore, Realtime Database e Storage. Significa che l'oggetto di configurazione con apiKey e projectId è pubblico per design (identifica il progetto, non autorizza nulla) e che l'unica barriera tra un visitatore e i tuoi dati sono le regole di sicurezza. Ogni prodotto ha le sue: Firestore, Realtime Database e Storage si configurano separatamente, e un'app di solito ha aperto quello che nessuno ha guardato.

Le regole rispondono a "chi può cosa"

Una regola riceve la richiesta con l'utente autenticato (request.auth), il documento che si vuole leggere o scrivere e i nuovi dati (request.resource.data). Con questo decide. La distinzione chiave è tra autenticato (c'è una sessione) e autorizzato (quella sessione può vedere quel documento): request.auth != null controlla solo il primo, e registrarsi è gratis. Le regole validano anche ciò che si scrive, perché un utente non si metta isAdmin: true nel proprio profilo.

Cosa protegge oltre alle regole

  • App Check. Richiede che le richieste arrivino dalla tua app reale (con reCAPTCHA o Play Integrity) e non da uno script con il tuo projectId. Frena gli abusi e le fatture inattese per letture massive.
  • Restrizione della chiave API. Nella console di Google Cloud, limita la chiave ai domini del tuo sito e alle API che usi. Non sostituisce le regole, ma chiude una porta.
  • Auth. Domini autorizzati per l'accesso, protezione dall'enumerazione delle email, verifica dell'email, solo i metodi di accesso che usi davvero, autenticazione a più fattori se gestisci dati sensibili.
  • Cloud Functions come server. Tutto ciò che ha bisogno di una chiave segreta (pagamenti, email, IA) va in una funzione, con il segreto in Secret Manager, e il client chiama la funzione. Attenzione: una funzione HTTP è pubblica per tutta internet a meno che tu non verifichi il token dell'utente o usi una funzione callable con App Check.
  • Budget. Firebase fa pagare per lettura e per invocazione. Avvisi di budget in Google Cloud e limiti nelle regole (request.query.limit) evitano che un loop o un attaccante ti lascino una fattura.

Hosting: cosa mette Firebase e cosa no

Firebase Hosting dà TLS automatico, CDN e reindirizzamento a HTTPS. Non mette header di sicurezza: si aggiungono in firebase.json. E serve tutto ciò che c'è nella cartella pubblica, compreso un .env copiato per errore.

Parte 2: cosa l'IA sbaglia con Firebase

  • Regole in modalità test, e poi if true. L'IA lascia le regole che aprono tutto per trenta giorni; alla scadenza l'app si rompe e la soluzione rapida è aprirle per sempre.
  • request.auth != null come unica condizione. Qualsiasi utente registrato legge i dati di tutti gli altri.
  • Scritture senza validazione. Il profilo ha role o credits e la regola di update non esclude quei campi.
  • Altre chiavi nel bundle. Accanto alla configurazione di Firebase compaiono la chiave segreta di Stripe, quella di OpenAI o quella di un servizio email. Dettaglio in segreti che la tua app fa trapelare nel browser.
  • Funzioni HTTP che non controllano l'utente. La funzione che incassa, invia email o chiama un modello risponde a chiunque conosca l'URL.
  • Storage con regole copiate da Firestore. allow read, write: if request.auth != null in storage.rules: qualsiasi utente legge i file degli altri e carica quello che vuole.
  • Senza App Check, senza header, senza avvisi. Tre caselle che nessuno spunta perché l'app "funziona già".

Un blocco da incollare nel tuo progetto

Header di sicurezza in firebase.json (la Content-Security-Policy va a parte perché dipende dai tuoi script):

{
  "hosting": {
    "public": "dist",
    "headers": [
      {
        "source": "**",
        "headers": [
          { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
          { "key": "X-Content-Type-Options", "value": "nosniff" },
          { "key": "X-Frame-Options", "value": "DENY" },
          { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
          { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
        ]
      }
    ]
  }
}

E un punto di partenza per firestore.rules: tutto chiuso di default, ogni utente il proprio documento e campi di privilegio protetti.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null && request.auth.uid == userId
        && !request.resource.data.keys().hasAny(['role', 'isAdmin', 'plan', 'credits']);
      allow update: if request.auth != null && request.auth.uid == userId
        && !request.resource.data.diff(resource.data).affectedKeys()
           .hasAny(['role', 'isAdmin', 'plan', 'credits']);
    }
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Aggiungi poi una regola esplicita per collezione; l'ultima, con if false, garantisce che qualsiasi collezione nuova nasca chiusa.

Un prompt di revisione prima di pubblicare

Rivedi la sicurezza di questa app con Firebase e non cambiare ancora nulla. Rispondi con una lista:
1. Regole di Firestore, Realtime Database e Storage che permettono l'accesso a chiunque, con data in modalità test o con request.auth != null come unica condizione.
2. Regole di scrittura che non validano i campi, in particolare role, isAdmin, plan o credits.
3. Chiavi diverse dalla configurazione di Firebase presenti nel codice del browser, con file e riga.
4. Cloud Functions HTTP che non verificano il token dell'utente, e funzioni che leggono segreti dal codice invece che da Secret Manager.
5. Se App Check è attivo e se la chiave API è limitata per dominio.
6. Header di sicurezza in firebase.json e file nella cartella pubblica che non dovrebbero esserci.
Per ogni punto, proponi la regola o la modifica esatta e aspetta la mia conferma.

Verifica il risultato dall'esterno

Il tuo projectId è nel bundle, quindi chiunque può fare questo. L'API REST di Firestore senza token:

curl -s "https://firestore.googleapis.com/v1/projects/TUO_PROGETTO/databases/(default)/documents/users" | head -c 400
curl -sI https://tuodominio.com | grep -iE "strict-transport|x-frame|x-content-type"

Il risultato corretto è un errore di permessi sul primo (se restituisce documenti, la collezione è aperta) e gli header sul secondo. Ripeti il primo con ogni collezione e con Storage. Scanaris fa queste verifiche e una quarantina di altre in 30 secondi: rileva la configurazione di Firebase nel tuo bundle, prova le collezioni abituali senza autenticazione, cerca altre chiavi nel JavaScript, controlla header, CORS, cookie e file esposti, e ti dà un fix prompt per ogni riscontro da incollare in Lovable, Bolt o Cursor. Se la tua app usa Supabase invece di Firebase, la guida Supabase è l'equivalente.

Domande frequenti

Devo nascondere l'apiKey di Firebase?

No. È pubblica per design e identifica il progetto. A proteggere i dati sono le regole e App Check. Quello che conviene fare è limitarla ai tuoi domini in Google Cloud.

Le Cloud Functions sono private?

Una funzione HTTP è un URL pubblico. Verifica il token dell'utente dentro la funzione o usa funzioni callable con App Check. Le funzioni che reagiscono a eventi (un documento creato, un file caricato) non hanno URL e sono davvero interne.

Come provo le regole senza rompere l'app?

Con il simulatore della console (scheda Regole) per provare letture specifiche, e con l'emulatore locale per i test automatici. Cambia le regole con l'app aperta in un'altra scheda e verifica che ciò che deve funzionare continui a funzionare.

Controlli correlati

La tua app Firebase supera questi controlli?

Scansionala gratis e ottieni un prompt di fix per ogni problema che troviamo.

Scansiona il mio sito gratis