The Firebase security rules checklist for AI-built apps
Your Firebase web config, apiKey included, is public by design: it ships in your JavaScript and anyone can read it. The only thing between that config and your users' data is your security rules, and AI tools often leave
Your Firebase web config, apiKey included, is public by design: it ships in your JavaScript and anyone can read it. The only thing between that config and your users' data is your security rules, and AI tools often leave them in test mode or loosen them until the app "works". Here's how to check them in about ten minutes.
1. Find test-mode and allow-all rules
From your project folder:
grep -nE "if true|request.time <|\"\.(read|write)\": *true" firestore.rules storage.rules database.rules.json
Any hit is an open door. allow read, write: if request.time < timestamp.date(...) is the default test-mode rule: everything is public until that date, and when it passes the app breaks and someone "fixes" it with if true.
2. "Signed in" is not "allowed"
allow read, write: if request.auth != null; lets every user who signs up read and change every other user's documents. Tie each document to its owner:
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
Where the owner is a field, check it on both sides: resource.data.ownerId == request.auth.uid for reads and updates, and request.resource.data.ownerId == request.auth.uid for creates.
3. Lock the fields users must not change
If users can update their own profile document, they can also set role: "admin" or credits: 999999 on it unless your rules forbid it:
allow update: if request.auth.uid == userId
&& !request.resource.data.diff(resource.data).affectedKeys().hasAny(['role', 'plan', 'credits']);
4. Check the Realtime Database too
If you use it, database.rules.json with ".read": true or ".write": true at the root opens the whole database. Scope it per user:
{
"rules": {
"users": {
"$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" }
}
}
}
5. Check Storage rules
Storage has its own rules file, and AI tools often leave it wide open. Scope uploads to the user's own folder and limit size and type:
match /b/{bucket}/o {
match /uploads/{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/.*');
}
}
6. Keep admin credentials out of the browser and the repo
The web config is fine to ship. A service-account key (a JSON file with "type": "service_account" and a private_key) is not: it bypasses every rule. It belongs only on a server or in Cloud Functions. Check your history too:
git log --all --oneline -S '"private_key"'
If that prints anything, delete the key in the Google Cloud console (IAM → Service accounts → Keys) and create a new one. Removing the file from the repo is not enough.
7. Prove it from the outside
Signed out, a private collection must refuse to list:
curl "https://firestore.googleapis.com/v1/projects/<project-id>/databases/(default)/documents/<collection>?pageSize=5"
You want 403 PERMISSION_DENIED. If you get documents back, anyone on the internet can too. The Rules Playground in the Firebase console lets you test signed-in cases, such as user A reading user B's document.
Check your repo automatically. Leakproof's free scanner flags Firebase rules left in test mode or set to if true, admin keys in client code, secrets in public env vars and more. It runs locally:
npx github:beingRealFrank/leakproof
Want someone to go through all of this, plus your live project, and send fix PRs? See the fixed-price audits.
Written with AI assistance. Found a mistake? Open an issue at https://github.com/beingRealFrank/leakproof/issues.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.