← Terug naar de blog
BeveiligingScanaris Team · 6 min lezen · October 04, 2026

De meest voorkomende beveiligingsfouten in Firebase

Firebase is de favoriete backend van veel met AI gebouwde apps: Lovable, Bolt of Cursor koppelen het in minuten en je hebt authenticatie, een database en bestanden zonder een server op te zetten. Het probleem is dat het beveiligingsmodel het omgekeerde is van dat van een traditionele backend. Hier praat de browser rechtstreeks met de database, dus er is geen server die verzoeken filtert: de beveiligingsregels zijn je enige barrière, en één slecht geschreven regel legt alle data bloot. Deze gids loopt de tien fouten door die het vaakst voorkomen, met de foute en de goede regel in elk geval, en eindigt met hoe je het zelf controleert.

1. Regels in testmodus, of wat erna komt

Bij het aanmaken van een database biedt Firebase je de "testmodus" aan: alles open gedurende dertig dagen. De regel ziet er zo uit:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2026, 11, 3);
    }
  }
}

Tot die datum kan iedereen met je projectId (die in de browsercode staat) de hele database lezen en schrijven. En het ergste komt daarna: bij het verlopen werkt de app niet meer, de ontwikkelaar zoekt een snelle oplossing en vervangt de datum door if true. Nu is het gat permanent. De oplossing is vanaf dag één regels per collectie schrijven, gebaseerd op wie de gebruiker is en van wie het document is.

2. allow read: if true op gebruikersdata

Er zijn collecties die publiek mogen zijn (een productcatalogus, de posts van een blog). Maar allow read: if true op users, orders of messages betekent dat iedereen de volledige lijst kan downloaden. De juiste manier om documenten per gebruiker te beschermen:

match /users/{userId} {
  allow read, write: if request.auth != null
                     && request.auth.uid == userId;
}

Elke gebruiker leest en schrijft alleen zijn eigen document. Voor data die meerdere mensen delen (een team, een project) sla je de ledenlijst op in het document en controleer je die in de regel.

3. "Geauthenticeerd" verwarren met "geautoriseerd"

De regel allow read: if request.auth != null lijkt veilig en is de meest voorkomende fout. Hij zegt: elke ingelogde gebruiker mag lezen. Maar je registreren bij je app is gratis en duurt tien seconden, dus in de praktijk is het hetzelfde als open. Geauthenticeerd beantwoordt wie je bent; geautoriseerd wat je mag zien. De regels moeten het tweede beantwoorden.

4. Gevoelige data in leesbare documenten

Een publiek profiel met naam en avatar is redelijk. Hetzelfde document met e-mail, telefoon, adres en een toegangstoken niet. Als andere gebruikers een deel van het profiel moeten kunnen zien, scheid dan publiek van privé in twee documenten of in een subcollectie private met strengere regels. Wat niet in een leesbaar document staat, kan niet lekken.

5. Denken dat de Firebase-configuratie een geheim is

Het object met apiKey, authDomain en projectId gaat bewust naar de browser: het identificeert je project, het autoriseert niets. Het in de bron zien is geen fout, en het is niet wat je moet verbergen. Wat je wel met die sleutel moet doen: hem in de Google Cloud-console beperken tot de domeinen van je site (beperking op HTTP-referrer) en App Check inschakelen, dat eist dat verzoeken van je echte app komen en niet van een script.

6. Andere sleutels zijn wél geheim

De ernstige fout is een andere: naast de Firebase-configuratie bevat de bundle de geheime sleutel van Stripe, die van OpenAI of die van een e-maildienst omdat "dat makkelijker was". Die sleutels geven toegang tot geld en tot accounts van derden. Hun plek is een Cloud Function met de geheimen in omgevingsvariabelen, en de browser roept de functie aan, nooit de dienst rechtstreeks. De details staan in geheimen die je app in de browser lekt.

7. Storage zonder eigen regels

Cloud Storage heeft zijn eigen regels en die worden vaak vergeten. Met allow read, write: if request.auth != null kan elke geregistreerde gebruiker de bestanden van anderen lezen, van alles uploaden naar elk pad en je quotum vullen. Een redelijke regel beperkt het pad tot de gebruiker en valideert grootte en type:

match /users/{userId}/{fileName} {
  allow read: if request.auth != null && request.auth.uid == userId;
  allow write: if request.auth != null
               && request.auth.uid == userId
               && request.resource.size < 5 * 1024 * 1024
               && request.resource.contentType.matches('image/.*');
}

8. Open Realtime Database

Gebruik je de Realtime Database in plaats van Firestore, dan is het equivalent ".read": true in de root. De regels zijn een andere taal, maar de logica is dezelfde: niets open in de root, en rechten per tak met auth.uid.

9. Schrijven zonder valideren

Schrijven toestaan aan de eigenaar van het document is niet genoeg als je niet valideert wat hij schrijft. Een gebruiker kan vanuit de browserconsole isAdmin: true of plan: "pro" aan zijn eigen profiel toevoegen. Valideer de velden met request.resource.data: welke sleutels bestaan, van welk type ze zijn en dat gevoelige velden niet veranderen.

allow update: if request.auth.uid == userId
  && !request.resource.data.diff(resource.data).affectedKeys()
       .hasAny(['isAdmin', 'plan', 'credits']);

10. De rekening vergeten

Firebase rekent per leesbewerking. Een regel die list zonder limiet toestaat op een grote collectie, laat een script miljoenen documenten lezen en bezorgt je een onverwachte rekening. Beperk query's vanuit de regels (request.query.limit <= 100), schakel App Check in en stel budgetwaarschuwingen in bij Google Cloud.

Hoe je het zelf controleert

  • Regelsimulator. In de Firebase-console, tabblad Regels, staat een simulator waarin je een leesbewerking test als anonieme gebruiker of met een specifieke UID. Probeer users te lezen zonder sessie: dat moet geweigerd worden.
  • Emulator met tests. De lokale emulator laat je geautomatiseerde regeltests schrijven. Het is de enige manier om ze niet te breken als je ze wijzigt.
  • Van buitenaf, zonder token. De REST-API van Firestore antwoordt iedereen:
curl "https://firestore.googleapis.com/v1/projects/JOUW_PROJECT/databases/(default)/documents/users"

Geeft hij documenten terug, dan is die collectie open. Geeft hij een rechtenfout, dan werkt de regel. Herhaal dit voor elke collectie die je hebt.

Scanaris controleert je Firebase van buitenaf

Scanaris detecteert de Firebase-configuratie in je bundle, controleert of de gebruikelijke collecties zonder authenticatie antwoorden, zoekt naar andere sleutels die niet in de browser horen en controleert headers, CORS en blootgestelde bestanden. Voor elke bevinding krijg je een fix prompt met de exacte regel of wijziging om in Lovable, Bolt of Cursor te plakken. Het zijn alleen-lezen controles op wat al publiek is. De volledige lijst risico's staat in de beveiligingsgids voor Firebase, en vóór de lancering is het de moeite de beveiligingschecklist door te lopen.

Veelgestelde vragen

Is het een probleem dat mijn Firebase-apiKey in de code staat?

Op zichzelf niet: hij identificeert het project, hij geeft geen rechten. Wat de data beschermt, zijn de regels. Beperk de sleutel wel tot je domeinen en schakel App Check in om misbruik te voorkomen.

Wat doe ik als mijn regels op dit moment open staan?

Eerst sluiten: zet regels per collectie met request.auth.uid, ook als een functie daardoor stopt, en repareer de app daarna. Controleer vervolgens in de gebruikslogs of er afwijkende leesbewerkingen waren en, als er persoonsgegevens bloot lagen, overweeg of je het moet melden.

Kan ik mijn AI vragen de regels te schrijven?

Ja, en dat doet ze meestal goed als je de structuur van je collecties geeft en wie wat moet zien. Maar test ze in de simulator voordat je publiceert: een AI schrijft ook if request.auth != null in de overtuiging dat het veilig is.

Hoe staat je site ervoor?

Laat Scanaris er even overheen gaan en check het in 30 seconden, gratis.

Mijn site scannen

Gerelateerde checks

Beveiligingsgidsen per stack