Shypset

Firebase security: rules, not the config, protect your data

Every Firebase web app ships its config, including an API key, to the browser. That worries people, but it is by design. The real question is what your security rules allow. Here is what goes wrong in Firebase apps and how Shypset checks them from outside.

The Firebase config is public on purpose

The firebaseConfig object with apiKey, authDomain and projectId identifies your project; it does not grant access to data. Access to the Realtime Database, Firestore and Storage is decided by security rules evaluated on Google’s side. So when we find the config in your bundle, we report it as information, not as a leak.

The danger is in the rules. A database created in test mode allows reads and writes for everyone until a set date, and rules like ".read": true at the root are often left in place because the app works with them.

What goes wrong in Firebase apps

  • Realtime Database rules with ".read": true at the root: the whole database can be downloaded with one request.
  • Firestore rules still in test mode, or allow read, write: if true;.
  • Rules that check request.auth != null but not that the document belongs to the user.
  • A Google API key that has other APIs enabled without restrictions, such as Maps or Generative AI, so it can be used on someone else’s bill.
  • Server credentials, like a service account JSON, bundled into the frontend.

What Shypset checks on a Firebase app

Public, on every scan: we detect Firebase configuration in your page and scripts, flag an exposed Realtime Database URL, and search the bundle for secrets including private key blocks that should never be in a browser. A Firebase browser key on its own is not reported as a leak, for the reason above, so restricting it is a step you do yourself.

Verified, after domain verification: we send one anonymous GET /.json?shallow=true to the Realtime Database your app uses. If it answers, we report how many top-level keys it has and nothing else. Firestore rules are not tested yet, so a clean result covers the Realtime Database only.

Shypset is a passive external check. It does not log in to your app and does not test application logic such as SQL injection or IDOR, so a clean report means nothing is visible from outside, not that the app is secure.

How to fix it

In the Firebase console, replace open rules with rules that require auth and scope data to the user, for example {"rules": {"users": {"$uid": {".read": "auth != null && auth.uid == $uid"}}}}. Do the same for Firestore and Storage. Restrict the API key in Google Cloud to your domains and the APIs you use. Publish the rules, then rescan.

Example finding

A Verified finding on a Firebase app, with the fix prompt.

criticalFirebase Realtime Database is readable without login

Evidence

Database: example-app-default-rtdb.firebaseio.com
Request: GET /.json?shallow=true
HTTP status: 200
Top-level keys: 4

Fix prompt

Our Firebase Realtime Database allows anonymous reads at the root. Rewrite database.rules.json so nothing is readable or writable at the root, users/$uid is readable and writable only when auth.uid == $uid, and any public data lives under a separate node with read-only access. Explain each rule and tell me how to deploy them with the Firebase CLI.

Questions

Should I hide my Firebase apiKey?
You cannot, and you do not need to. Restrict it to your domains and lock down the security rules instead.
Does the probe change anything in my database?
No. It is a single read request with no credentials, and only the key count is kept.

Check your Firebase app

Paste your app URL on the home page, then verify the domain to test the database rules.

Scan your Firebase app