A Firebase web app ships its config (project ID, API key, database URL, storage bucket) to every visitor. That is by design and the API key is not a secret. The only thing standing between the internet and your data is your security rules.
What SecScan tests
Using only what the page already publishes, with read-only requests:
- Firestore: twenty common collection names, unauthenticated. A finding needs documents actually returned.
- Realtime Database: the root
.json, unauthenticated. - Cloud Storage: listing the bucket. A finding needs a file name actually returned.
A 401 or 403, an empty result or an unreadable response is never reported as a finding. A collection that is readable but looks like public catalogue content (posts, products, events, with nothing personal in it) is an Info note to confirm it is meant to be public, not a Critical.
Fixes
Firestore, require sign-in and scope by owner:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/{document=**} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}
}
}
Realtime Database:
{ "rules": { "users": { "$uid": { ".read": "auth.uid === $uid", ".write": "auth.uid === $uid" } } } }
Cloud Storage:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{uid}/{allPaths=**} {
allow read, write: if request.auth != null && request.auth.uid == uid;
}
}
}
Never use allow read, write: if true. It is the development default and the most common cause of
an open project. Also enable App Check to restrict the API to your own app.
Last reviewed 2026-09-26