Firebase security rules open to anyone: how to check and fix them
SHORT ANSWER
Your Firebase config (the apiKey in your frontend) is not a secret. Anyone can see it. What actually protects your data is your security rules. If your rules say allow read, write: if true;, or you're still on "test mode", anyone on the internet can read, change or delete everything in your database. Fix it by writing rules that check who is asking (request.auth.uid) and what they're allowed to touch.
Why this happens
When you create a Firestore database, Firebase offers test mode. It opens the database to everyone for 30 days so you can build quickly. Many apps ship before anyone comes back to change it. Another common version:
allow read, write: if true;AI coding tools also often "fix" permission errors by loosening the rules until the error goes away.
The quieter mistake: "signed in" is not "allowed"
match /orders/{orderId} { allow read, write: if request.auth != null;}This looks safe, but it means any signed-in user can read and edit every order, including other people's. Signing up is free, so this is almost as open as if true.
How to check your app
- Open the Firebase console → Firestore Database → Rules. Also check Storage → Rules.
- Look for any of these:
if true- a date check like
request.time < timestamp.date(...)(test mode) if request.auth != nullon data that belongs to one user- a wildcard like
match /{document=**}that applies one loose rule to everything
- Use the Rules Playground in the console to simulate an unauthenticated read of a collection. If it's allowed, your data is public.
How to fix it
Tie every document to its owner and check it:
rules_version = '2';service cloud.firestore { match /databases/{database}/documents { // Each user can only read and edit their own profile match /users/{userId} { allow read, write: if request.auth != null && request.auth.uid == userId; } // Orders: only the owner can read; only the owner can create, and only for themselves match /orders/{orderId} { allow read: if request.auth != null && resource.data.userId == request.auth.uid; allow create: if request.auth != null && request.resource.data.userId == request.auth.uid; allow update, delete: if false; // change orders on the server, not from the browser } }}Rules of thumb:
- Deny by default. Anything you don't explicitly allow is blocked.
- Check
resource.data(what's stored) on reads, updates and deletes, andrequest.resource.data(what's being written) on creates and updates. - Never let the browser set prices, roles, credits or another user's ID. Do those on the server (Cloud Functions or your backend).
- Apply the same thinking to Storage rules: users should only write to their own folder, for example
match /users/{userId}/{file}.
FAQ
Is my Firebase API key a secret?
No. It identifies your project and is meant to be in the browser. Security comes from your rules and from App Check, not from hiding the key.
Does test mode close automatically after 30 days?
The default test-mode rule stops allowing access after its date, which can break your app suddenly. It's not a security plan. Write real rules before you launch.
Is request.auth != null enough?
Only for data that every signed-in user is meant to see, like a public product list. For anything personal (profiles, orders, messages), also check that the user owns the document.
How do I know if someone already accessed my data?
Look at Firestore usage in the Firebase console for unusual read or write spikes. If your rules were open, assume the data could have been read, and tell affected users if it included personal information.
Can SetRepo check this for me?
Yes. A Quick scan flags open and test-mode rules in your firestore.rules and storage.rules. A Deep scan also reviews each rule against how your app actually reads and writes data.