TentyAll guides

Firebase rules

Firebase databases protect their data with rules. The Realtime Database and Firestore web addresses ship in your page, so the rules are the only protection the data has.

What it is

The Realtime Database answers a web request at https://NAME.firebaseio.com/.json. Firestore answers at firestore.googleapis.com for any collection in your project. Both return data to anyone when the rules allow reading without sign in.

Why it matters

Test mode rules and allow read: if true are common in apps that went live quickly. Anyone who finds the project id in your scripts can then read users, orders, messages or whatever the collection holds, and a script can walk through all of it. Tenty rates the finding critical when the top level keys or field names look personal, such as email, phone or token, and high otherwise.

How Tenty checks it

Tenty reads the files of your own site and collects Realtime Database addresses, project ids and the collection names your code calls. For each database it asks for the top level key list. For each collection it asks for one document. This runs for verified owners only, with up to 20 collections and 3 projects per scan, all read-only. The finding names the keys or field names. Values stay out of the report.

How to fix it

Change the rules so that reading needs a signed in user and the rule says whose data it is.

Realtime Database rules:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid === $uid",
        ".write": "auth != null && auth.uid === $uid"
      }
    }
  }
}

Firestore rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /orders/{orderId} {
      allow read: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

Publish the rules, then run the reproduce command again and expect a permission denied answer.

How to reproduce

Realtime Database, with the address from the finding:

curl -sS 'https://NAME.firebaseio.com/.json?shallow=true'

Firestore, with the project and collection from the finding:

curl -sS 'https://firestore.googleapis.com/v1/projects/PROJECT/databases/(default)/documents/COLLECTION?pageSize=1'

A JSON answer with keys or documents means the rules let anyone read. An error with PERMISSION_DENIED means the rules hold.