← Guides par stack

Firebase

Sécurité pour ton app avec Firebase

La sécurité de Firebase dépend presque entièrement des règles que tu écris. Avec des règles en mode test ou trop ouvertes, ta base de données est à la portée de n'importe qui. Vérifie ça avant d'ouvrir ton app.

Risques typiques dans Firebase

Des règles en mode test

Le mode test autorise la lecture et l'écriture pour tout le monde. Beaucoup de gens lancent sans le changer, laissant la base de données grande ouverte.

Confondre la clé publique avec de la sécurité

La config de Firebase est publique par conception ; ce qui protège tes données, ce sont les règles, pas le fait de cacher cette clé. Supposer le contraire mène à des données exposées.

D'autres clés dans le frontend

À côté de la config de Firebase se glissent souvent des clés qui sont vraiment secrètes (paiements, email, IA). Celles-là ne doivent jamais être dans le JavaScript du navigateur.

« Sécurité Firebase », ce sont deux choses qu'il vaut mieux séparer. La première, c'est le modèle de Firebase : le navigateur parle directement à la base de données et au stockage, donc aucun serveur ne filtre, et la protection vit dans les règles, dans App Check et dans la configuration du projet. La seconde, c'est ce que Lovable, Bolt ou Cursor font avec Firebase en générant du code, et c'est de là que viennent presque tous les trous. Ce guide explique le modèle, passe en revue ce que l'IA fait mal, te laisse un firebase.json et des règles de base à coller, un prompt de revue et la vérification de l'extérieur. Les dix erreurs de règles les plus courantes, avec la mauvaise règle et la bonne, sont dans les erreurs de sécurité les plus courantes dans Firebase.

Partie 1 : comment fonctionne la sécurité dans Firebase

Le client parle aux services, pas à ton serveur

Dans une appli Firebase typique, il n'y a pas de backend à toi : le SDK du navigateur lit et écrit directement dans Firestore, Realtime Database et Storage. Ça signifie que l'objet de configuration avec apiKey et projectId est public par conception (il identifie le projet, il n'autorise rien) et que la seule barrière entre un visiteur et tes données, ce sont les règles de sécurité. Chaque produit a les siennes : Firestore, Realtime Database et Storage se configurent séparément, et une appli a généralement ouvert celui que personne n'a regardé.

Les règles répondent à « qui peut quoi »

Une règle reçoit la requête avec l'utilisateur authentifié (request.auth), le document qu'on veut lire ou écrire et les nouvelles données (request.resource.data). Avec ça, elle décide. La distinction clé est entre authentifié (il y a une session) et autorisé (cette session peut voir ce document) : request.auth != null ne vérifie que le premier, et s'inscrire est gratuit. Les règles valident aussi ce qui est écrit, pour qu'un utilisateur ne se mette pas isAdmin: true sur son propre profil.

Ce qui protège en plus des règles

  • App Check. Exige que les requêtes viennent de ta vraie appli (via reCAPTCHA ou Play Integrity) et pas d'un script avec ton projectId. Il freine les abus et les factures inattendues dues aux lectures massives.
  • Restriction de la clé d'API. Dans la console Google Cloud, limite la clé aux domaines de ton site et aux API que tu utilises. Ça ne remplace pas les règles, mais ça ferme une porte.
  • Auth. Domaines autorisés pour la connexion, protection contre l'énumération d'e-mails, vérification de l'e-mail, uniquement les méthodes de connexion que tu utilises vraiment, authentification multifacteur si tu manipules des données sensibles.
  • Cloud Functions comme serveur. Tout ce qui a besoin d'une clé secrète (paiements, e-mail, IA) va dans une fonction, avec le secret dans Secret Manager, et le client appelle la fonction. Attention : une fonction HTTP est publique pour tout internet, sauf si tu vérifies le jeton de l'utilisateur ou si tu utilises une fonction callable avec App Check.
  • Budget. Firebase facture à la lecture et à l'invocation. Des alertes de budget dans Google Cloud et des limites dans les règles (request.query.limit) évitent qu'une boucle ou un attaquant te laisse une facture.

Hosting : ce que Firebase met et ce qu'il ne met pas

Firebase Hosting fournit le TLS automatique, un CDN et la redirection vers HTTPS. Il ne pose pas d'en-têtes de sécurité : ils s'ajoutent dans firebase.json. Et il sert tout ce qui est dans le dossier public, y compris un .env copié par erreur.

Partie 2 : ce que l'IA fait mal avec Firebase

  • Des règles en mode test, puis if true. L'IA laisse les règles qui ouvrent tout pendant trente jours ; à l'expiration, l'appli casse et la solution rapide, c'est de les ouvrir pour toujours.
  • request.auth != null comme seule condition. N'importe quel utilisateur inscrit lit les données de tous les autres.
  • Des écritures non validées. Le profil a role ou credits et la règle d'update n'exclut pas ces champs.
  • D'autres clés dans le bundle. À côté de la configuration Firebase apparaissent la clé secrète de Stripe, celle d'OpenAI ou celle d'un service d'e-mail. Détail dans les secrets que ton appli laisse fuiter dans le navigateur.
  • Des fonctions HTTP qui ne vérifient pas l'utilisateur. La fonction qui encaisse, envoie des e-mails ou appelle un modèle répond à quiconque connaît l'URL.
  • Un Storage avec des règles copiées de Firestore. allow read, write: if request.auth != null dans storage.rules : n'importe quel utilisateur lit les fichiers des autres et envoie ce qu'il veut.
  • Pas d'App Check, pas d'en-têtes, pas d'alertes. Trois cases que personne ne coche parce que l'appli « marche déjà ».

Un bloc à coller dans ton projet

Les en-têtes de sécurité dans firebase.json (la Content-Security-Policy va à part parce qu'elle dépend de tes scripts) :

{
  "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=()" }
        ]
      }
    ]
  }
}

Et un point de départ pour firestore.rules : tout fermé par défaut, chaque utilisateur son document et les champs de privilège protégés.

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;
    }
  }
}

Ajoute ensuite une règle explicite par collection ; la dernière, avec if false, garantit que toute nouvelle collection naît fermée.

Un prompt de revue avant de publier

Passe en revue la sécurité de cette appli Firebase et ne change rien pour l'instant. Réponds avec une liste :
1. Règles Firestore, Realtime Database et Storage qui autorisent l'accès à n'importe qui, avec une date de mode test ou avec request.auth != null comme seule condition.
2. Règles d'écriture qui ne valident pas les champs, en particulier role, isAdmin, plan ou credits.
3. Clés autres que la configuration Firebase présentes dans le code du navigateur, avec fichier et ligne.
4. Cloud Functions HTTP qui ne vérifient pas le jeton de l'utilisateur, et fonctions qui lisent des secrets dans le code au lieu de Secret Manager.
5. Si App Check est activé et si la clé d'API est restreinte par domaine.
6. En-têtes de sécurité dans firebase.json et fichiers du dossier public qui ne devraient pas y être.
Pour chaque point, propose la règle ou le changement exact et attends ma confirmation.

Vérifie le résultat de l'extérieur

Ton projectId est dans le bundle, donc n'importe qui peut faire ceci. L'API REST de Firestore sans jeton :

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

Le bon résultat, c'est une erreur de permissions sur la première (si elle renvoie des documents, la collection est ouverte) et les en-têtes sur la seconde. Répète la première pour chaque collection et pour Storage. Scanaris fait ces vérifications et une quarantaine d'autres en 30 secondes : il détecte la configuration Firebase dans ton bundle, sonde les collections habituelles sans authentification, cherche d'autres clés dans le JavaScript, contrôle en-têtes, CORS, cookies et fichiers exposés, et te donne un fix prompt pour chaque constat à coller dans Lovable, Bolt ou Cursor. Si ton appli utilise Supabase au lieu de Firebase, le guide Supabase est l'équivalent.

Questions fréquentes

Dois-je cacher l'apiKey Firebase ?

Non. Elle est publique par conception et identifie le projet. Ce qui protège les données, ce sont les règles et App Check. Ce qui vaut la peine, c'est de la restreindre à tes domaines dans Google Cloud.

Les Cloud Functions sont-elles privées ?

Une fonction HTTP est une URL publique. Vérifie le jeton de l'utilisateur dans la fonction ou utilise des fonctions callable avec App Check. Les fonctions qui réagissent à des événements (un document créé, un fichier envoyé) n'ont pas d'URL et sont bien internes.

Comment tester les règles sans casser l'appli ?

Avec le simulateur de la console (onglet Règles) pour tester des lectures précises, et avec l'émulateur local pour des tests automatiques. Change les règles avec l'appli ouverte dans un autre onglet et vérifie que ce qui doit marcher marche toujours.

Vérifications liées

Ton app Firebase passe-t-elle ces vérifications ?

Analyse-la gratuitement et reçois un fix prompt pour chaque problème qu'on trouve.

Analyser mon site gratuitement