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.
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