Is a Firebase API key safe to expose in the browser?
By StackSiren · Published
Yes — Firebase's own docs say API keys for Firebase services identify your project and app; they are not a secret access token. Real protection for Firestore, Realtime Database and Storage comes from Firebase Security Rules and (for abuse) App Check, not from hiding apiKey in the web config.
That is the same shape as a Supabase publishable / anon key: public by design, dangerous only when rules are missing. Contrast with provider secrets (OpenAI, Stripe sk_, Gemini Developer API keys) that must never ship to the browser — exposed API keys, Is the Supabase anon key safe?, Is NEXT_PUBLIC_ safe?.
Why Firebase web API keys are public
Firebase automatically creates platform keys (Browser / Android / iOS) when you add apps. The web config object includes apiKey, authDomain, projectId, and so on — and Firebase documents that keys restricted to Firebase services do not need to be treated as secrets when you follow their guidelines.
What the key actually does:
- Routes requests to your Firebase / Google project for quota and billing.
- Identifies the app to Firebase services that expect a key on the client call.
What it does not do:
- Authorise a user to read or write your data. That is Security Rules (and Auth).
- Prove the caller is your genuine app binary. That is App Check.
Firebase also auto-applies API restrictions on Firebase-provisioned keys (widened historically in May 2024 for older unrestricted keys). You should still review APIs & Services → Credentials in Google Cloud and keep non-Firebase APIs off that key.
Rules are the protection
Clients talk to Firestore / RTDB / Storage directly. There is no server in the middle unless you add one. Firebase's rules docs are blunt: Security Rules are the safeguard blocking malicious users.
Locked mode (safe default when creating a database) denies everything:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Owner-scoped pattern (common for vibe-coded apps):
service cloud.firestore {
match /databases/{database}/documents {
match /notes/{userId}/{docId} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}
Dangerous “test mode” leftovers — rules that allow read/write if true, or that only check request.auth != null on sensitive collections without ownership checks — are how “my Firebase key leaked” threads usually go. The key was always visible; the rules were the bug.
Storage and Realtime Database have parallel locked / owner patterns in the same Firebase rules basics doc. Apply the same discipline there.
App Check (abuse layer, not a substitute for rules)
Firebase App Check attests that requests come from your genuine app / an untampered device, then attaches a short-lived token to calls. On the web, the built-in path uses reCAPTCHA Enterprise.
Use it to:
- Reduce drive-by abuse of your Firebase backends and some Google APIs from scripts that are not your app.
- Protect custom backends that verify App Check tokens.
Do not treat App Check as a replacement for Security Rules. Firebase documents them as complementary: Authentication identifies the user; App Check attests the app/device; Rules decide data access. App Check also does not eliminate all abuse — it raises the bar.
Enable enforcement only after the client SDK is integrated and you have monitored metrics in a non-enforcing mode, or you will lock out real users.
What must stay secret (even in a Firebase project)
Firebase's API key page calls out a critical exception: the Gemini Developer API key (Generative Language API) must never be included in client code or config. Create a separate, restricted key for billable non-Firebase Google APIs (Maps, Gemini, etc.), keep it on a server or Cloud Function, and never add those APIs to the allowlist of your public Firebase browser key.
Also keep server-only:
- Firebase Admin SDK credentials / service account JSON
- Any custom backend secrets
- Provider keys (Stripe
sk_, OpenAI, email/SMS)
If those appear in a web bundle, rotate first — same playbook as leaked OpenAI key.
How to test your rules (and the live config)
- Read the web config in your shipped app (or Firebase console → Project settings). Confirm
apiKeyis the Firebase browser key, not a Gemini / unrestricted Cloud key. - Open Google Cloud → APIs & Services → Credentials. Check API restrictions on that key: Firebase-related APIs only; no Generative Language API on the public key.
- Rules playground / emulator — in the Firebase console, use the Rules Playground (or local emulators) to simulate
get/list/createasunauthenticatedand asauth.uid == "user-a"againstuser-b's path. Expect denials. - Signed-out browser — on a site you own, try reading a private collection from the client SDK while logged out. You should get a permission error, not data.
- Passive scan — StackSiren's free first scan and exposed API key checker look for secret key shapes in the bundle. A Firebase
apiKeyshowing up is expected; ansk-/ service account JSON is not. Deep Scan ($49 one-off or $99/mo add-on) can go further on apps you own when you need authenticated checks.
Cursor and v0 apps that drop Firebase into a Next.js or Vite client should keep Admin SDK usage in Route Handlers / server actions only — never in client components.
Related reading
- Exposed API keys guide
- Is the Supabase anon key safe?
- Is NEXT_PUBLIC_ safe for API keys?
- Are VITE_ environment variables secret?
- How to store secrets in Supabase Edge Functions
FAQ
Google emailed me that my API key is publicly accessible. Am I breached? If it is the Firebase browser key, restricted to Firebase APIs, with solid Rules and (ideally) App Check, Firebase's docs say that pattern is expected. Still verify restrictions and that Gemini / other billable APIs are not on that key.
Can I delete apiKey from the web config? Only if you provide the key another way. Without a key, client calls to services that require one fail. Hiding it is not a security boundary.
Are Android/iOS keys different? They are also identifiers for those apps, matched via the platform config files. Data access is still Rules + App Check, not key secrecy.
Does App Check replace Auth? No. Auth identifies the user; App Check attests the app/device; Rules use Auth (and data) to allow or deny.
What should I do if test-mode rules shipped to production? Lock the rules immediately (deny by default), ship owner-scoped rules, then review audit logs / usage for abuse. The public API key did not cause the incident — the open rules did. StackSiren's first scan is free on sites you own; use Deep Scan when you need a deeper pass.
Fix guides for this topic
Platform checklists: Cursor · v0