Fix guide · high · firebase_storage_public_list

Firebase Storage bucket allows anonymous list

What this rule means

A GET to https://firebasestorage.googleapis.com/v0/b/<bucket>/o returned an object listing without an auth token. Your Storage rules permit anonymous reads on the default bucket — which means every file path is enumerable.

Why it matters

Storage rules follow the same request.time < ... test-mode shape as Firestore, with the same shipping pattern: apps go live before the date passes. The List API needs only allow read: if true (or a permissive match /{allPaths=**} block) to expose every object's path. Once an attacker has the path list, individual files can be retrieved over the same public REST endpoint — ID cards, receipts, screenshots, anything the app uploads.

How to fix it

Lock the rules to authenticated, path-scoped access. Console → Storage → Rules:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // Default: deny.
    match /{allPaths=**} {
      allow read, write: if false;
    }

    // Profile photos: any signed-in user can read; only the owner can write.
    match /users/{userId}/avatar.jpg {
      allow read: if request.auth != null;
      allow write: if request.auth != null
                   && request.auth.uid == userId
                   && request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }

    // Public assets the marketing site needs.
    match /public/{file} {
      allow read: if true;
      allow write: if false;
    }

  }
}

Key principles:

  1. Default-deny. Same shape as Firestore — explicit closed policy, then specific opens.
  2. Validate uploads. request.resource.size and request.resource.contentType prevent users from uploading 4 GB of arbitrary binary as their "avatar".
  3. Use path scoping for multi-tenant. /users/{userId}/... paired with request.auth.uid == userId enforces per-user isolation in one rule.
  4. Audit the public/ namespace separately. If you do need a public read path, keep its scope tight and never let it permit writes.

Full guide: /blog/firebase-rules-vibe-coded.

Did vibecheck flag this on your app?

If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.

Run another inspection