// TECHNOLOGIES / FIREBASE

Firebase

Firebase, proven from the outside.

Firebase secures access with Security Rules — but the console only shows you the rules you wrote, never whether an anonymous request actually gets through. NewScan scans from the attacker's seat: with only your public config it proves the exploitable misconfigurations that are live — a leaked service_account key, a world-readable or world-writable Realtime Database, public Storage, open Firestore, and auth email enumeration. Every signal is reproduced before it is recorded — and your public apiKey, which is meant to be public, is never flagged.

The console blind-spot

// why an external scan matters

Firebase's console shows the rules you authored — it can't show you that https://your-proj.firebaseio.com/.json returns your entire database to anyone with the URL, that a secret Admin SDK key shipped in your JavaScript bundle, or that a Storage bucket lists to the public. Those live in the deployed rules, the client code, and the public REST surface — the attacker's exact position, and exactly the evidence an auditor wants.

// THE CONSOLE SHOWS (RULES YOU WROTE)

The rule text in the Rules tab, the emulator's local behaviour, App Check enrollment — all as you configured them, not as they respond to an anonymous request from the internet.

// THE CONSOLE CAN'T SEE (NEWSCAN DOES)

An Admin SDK service_account key shipped in the browser bundle, whether /.json actually returns data to anon, whether an empty write is authorised, or whether a Storage bucket lists to the public.

Service-account key in the client bundle

// tool: scan_firebase  critical

The single most catastrophic Firebase mistake — and the one people confuse with the harmless apiKey. An Admin SDK service_account credential carries full admin: it bypasses every Security Rule and reads or writes every database, Firestore collection, Storage object, and the Auth user store. NewScan fetches the deployed bundles and flags it on an unambiguous shape.

// WHY THIS IS FALSE-POSITIVE-FREE

A finding is recorded only when the bundle carries a "type":"service_account" together with a PEM private_key. The public apiKey is a project identifier Google says is safe to publish — NewScan uses it as an input and never reports it, so a Firebase app is never flagged just for shipping its config.

GET /assets/app.[hash].js scan bundle → {"type":"service_account", "private_key":"-----BEGIN PRIVATE KEY-----…"} # critical: rotate the key + move it server-side. apiKey alone = NOT a finding.

World-readable / world-writable Realtime Database

// non-destructive · read + no-op write

An RTDB rule of .read: true exposes the whole tree; a .write: true lets anyone overwrite it. NewScan confirms reach without pulling your rows, and proves write-authorisation with a no-op that creates no data.

// REACH-SAFE READ PROBE  critical

GET /.json?shallow=true -> 200 {"users":true,"orders":true} # open — keys only, no rows -> 401 Permission denied # secure

// NO-OP WRITE DIFFERENTIAL  high

PATCH /_newscan_write_probe.json # empty {} body -> 200 # write authorised — zero keys written -> 401 Permission denied # secure

// THE LOAD-BEARING FP GUARD

Permission denied, a null body, or an empty listing is the secure state — NewScan never records it. Only returned data, a non-empty listing, or an authorised write records. The write probe sends an empty object, so it evaluates the .write rule while creating no data, and runs only in the active profile.

Public Storage, open Firestore & auth enumeration

// read-only · reach-safe

The same rule model governs Cloud Storage, Firestore, and Auth — and the same misconfigurations recur: a bucket that lists anonymously, a collection readable via the REST API, an Auth endpoint that reveals which emails are registered.

// PUBLIC STORAGE + OPEN FIRESTORE  high

GET /v0/b/<bucket>/o -> 200 {"items":[…]} # public bucket lists GET /v1/…/documents/<collection>?pageSize=1 -> 200 {"documents":[…]} # open collection

A 403 PERMISSION_DENIED, an empty items, or no documents is the secure state — not a finding. pageSize=1 proves reach without bulk export.

// AUTH EMAIL ENUMERATION  medium

POST /v1/accounts:createAuthUri {"identifier":"a@x.com"} -> {"registered":true} {"identifier":"zzz@x.com"} -> {"registered":false}

Only a clear true-vs-false differential records. Projects created after 2023-09-15 default to enumeration protection and return a generic response — no differential, no finding.

What NewScan records

// class · method · severity
Finding How NewScan finds it Severity
Service-account key leaked The client bundle carries "type":"service_account" + a PEM private_key. critical
World-readable RTDB /.json?shallow=true returns data (not 401/null). critical
World-writable RTDB An empty-body PATCH is authorised (200, not 401) — no data created. high
Public Storage bucket An anonymous /v0/b/<bucket>/o returns a non-empty listing. high
Open Firestore collection A REST documents/<collection> returns documents to anon (not 403). high
Auth email enumeration accounts:createAuthUri returns a registered true/false differential. medium

Recent Firebase security issues

// why these checks matter

The vulnerability classes above, seen at scale in the wild — mass surveys of open Firebase databases, and a headline breach that leaked exactly these two classes.

External links; referenced for context. Breach details are the publishers'.

How it's recorded

// audit-ready evidence

CATEGORY

The service-account leak maps to OWASP API2; RTDB/Storage/Firestore exposure to API1; the authorised write to API3; auth enumeration to API2.

SEVERITY

One calibrated severity per finding that translates into each framework's risk rating and remediation SLA — no inflated numbers.

EVIDENCE

Every finding stores the exact request and the shallow key list, the empty-write status, or the listing that proved it — never a row of your users' data.

Point it at your Firebase app.

NewScan is free and self-hosted — bring your own key. Scanning your own Firebase project is local to you, so it never depends on any hosted resource. The service-account, RTDB, Storage, Firestore, and auth checks run in the deterministic floor with no model or provider key at all — and it also understands the Firebase Local Emulator Suite.