Firebase Service Account Key Exposed in Client Code
What Is This Vulnerability?
Firebase Admin SDK service account credentials or private keys are included in client-side JavaScript or committed to a public repository. Unlike the Firebase client configuration (which is designed to be public), service account keys grant full administrative access to your Firebase project, including reading and writing all database records, managing users, and accessing Cloud Storage.
Why It Happens
Developers confuse the Firebase client config (which is safe to expose) with the Firebase Admin SDK service account key (which must stay private). Some tutorials mix client and server setup in the same file. Service account JSON files downloaded from the Firebase console are sometimes placed in the project root and committed by accident.
Example Code
import admin from "firebase-admin";
admin.initializeApp({
credential: admin.credential.cert({
projectId: "my-app-12345",
privateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIB...long-key...\n-----END RSA PRIVATE KEY-----\n",
clientEmail: "firebase-adminsdk-abc@my-app-12345.iam.gserviceaccount.com",
}),
});
export const db = admin.firestore();import admin from "firebase-admin";
admin.initializeApp({
credential: admin.credential.cert({
projectId: process.env.FIREBASE_PROJECT_ID,
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, "\n"),
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
}),
});
export const db = admin.firestore();How Hackers Exploit It
With a Firebase service account key, an attacker gains full admin access to the Firebase project. They can read and modify all Firestore and Realtime Database data, create and delete user accounts, access Cloud Storage files, and send push notifications. The service account often has permissions beyond Firebase, extending to other Google Cloud resources in the same project.
How to Fix It
Store service account credentials in environment variables or use Google Cloud's default application credentials. Never place the service account JSON file in your source tree. Add the JSON filename to .gitignore. For production, use workload identity federation or deploy to environments where credentials are provided automatically (Cloud Run, Cloud Functions).