-
Notifications
You must be signed in to change notification settings - Fork 161
Open
Labels
api: firestoreIssues related to the googleapis/nodejs-firestore API.Issues related to the googleapis/nodejs-firestore API.priority: p2Moderately-important priority. Fix may not be included in next release.Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Description
Environment details
- OS: Linux / Alpine
- Node.js version: 22.0.0
- npm version:
@google-cloud/firestoreversion:
Steps to reproduce
Firebase Admin SDK Not Bypassing Security Rules on Cloud Run
Issue Summary
Firebase Admin SDK with ServiceAccountCredential successfully bypasses Firestore security rules when running locally, but fails with PERMISSION_DENIED when running on Google Cloud Run with identical code and credentials.
Environment
- Local (Working): Bun 1.2 on macOS
- Cloud Run (Failing): Node.js 22 on Alpine Linux (also tested with Bun)
- Firebase Admin SDK: v13.6.0
- Firestore Database: Named database
integrations-hub - Security Rules:
allow read, write: if false;
Minimal Reproducible Code
firestore-init.ts
import { initializeApp, cert } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';
export async function initializeFirestore() {
const serviceAccountKey = process.env.FIREBASE_SERVICE_ACCOUNT_KEY;
const serviceAccount = JSON.parse(serviceAccountKey);
const app = initializeApp({
credential: cert(serviceAccount),
projectId: 'my-project'
});
const db = getFirestore(app, 'integrations-hub');
// Verify credential type
const credential = (app as any).options?.credential;
console.log('Credential Type:', credential?.constructor?.name); // ServiceAccountCredential
console.log('Client Email:', serviceAccount.client_email); // firebase-adminsdk-fbsvc@...
// Verify access token generation
const token = await credential.getAccessToken();
console.log('Access Token Generated:', !!token.access_token); // true
return db;
}
export async function testRead() {
const db = await initializeFirestore();
// This should bypass security rules according to Firebase docs
const snapshot = await db.collection('integrations').get();
console.log('Documents:', snapshot.size);
}Dockerfile (Cloud Run)
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "build/index.js"]Cloud Run Environment
env:
- name: FIREBASE_SERVICE_ACCOUNT_KEY
valueFrom:
secretKeyRef:
name: integrations-hub-firebase-key
key: latestService Account Details
{
"type": "service_account",
"project_id": "my-project",
"client_email": "firebase-adminsdk-fbsvc@my-project.iam.gserviceaccount.com"
}IAM Roles:
roles/datastore.ownerroles/firebase.sdkAdminServiceAgentroles/iam.serviceAccountTokenCreator
Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Actual Behavior
Local Execution (✅ Works)
Credential Type: ServiceAccountCredential
Access Token Generated: true
Documents: 180 <-- SUCCESS
Cloud Run Execution (❌ Fails)
Credential Type: ServiceAccountCredential
Client Email: firebase-adminsdk-fbsvc@my-project.iam.gserviceaccount.com
Access Token Generated: true
Access Token Length: 1024
Token Expires In: 3597s
hasDbCredential: true
hasSettings: true
Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
at callErrorFromStatus (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/call.js:32:23)
at onReceiveStatus (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/build/src/client.js:359:53)
Evidence
Cloud Run Logs (timestamp: 2026-01-09 13:44:04):
{
"message": "Successfully generated access token",
"hasAccessToken": true,
"tokenLength": 1024,
"expiresIn": 3597
}
{
"message": "Firestore DB object inspection",
"hasDbCredential": true,
"dbClientType": "Firestore",
"projectIdFromDb": "my-project",
"databaseIdFromDb": "integrations-hub"
}
{
"message": "Fetching integrations from Firestore",
"credentialType": "ServiceAccountCredential",
"hasCredential": true,
"dbClientAuth": {
"hasSettings": true,
"hasCredentials": true,
"projectId": "my-project",
"clientEmail": "firebase-adminsdk-fbsvc@my-project.iam.gserviceaccount.com"
}
}
// Immediately followed by PERMISSION_DENIEDExpected Behavior
According to Firebase documentation:
"The server client libraries automatically bypass Cloud Firestore Security Rules, and access data using privileged Admin SDK privileges"
The Admin SDK should bypass security rules on Cloud Run just as it does locally.
Workaround Tested
- ✅ Opening security rules to
if true→ Cloud Run works - ✅ Using the exact same service account key locally → works with
if false - ❌ Both Node.js and Bun runtimes on Cloud Run → still fails
- ❌ Using
@google-cloud/firestoredirectly instead offirebase-admin/firestore→ still fails - ✅ Verified IAM permissions are correct
Questions
- Why does the Admin SDK bypass rules locally but not on Cloud Run?
- Is there a Cloud Run-specific configuration needed for Admin SDK privilege escalation?
- Is this related to the named database (
integrations-hub) vs default database?
Additional Context
- The
(default)database exhibits the same behavior - Previously deleted and recreated the
(default)database (may have corrupted Firebase project config?) - Cloud Run service account has all necessary IAM roles
- Network: No VPC, HTTP/2 disabled, no service mesh
Making sure to follow these steps will guarantee the quickest resolution possible.
Thanks!
Metadata
Metadata
Assignees
Labels
api: firestoreIssues related to the googleapis/nodejs-firestore API.Issues related to the googleapis/nodejs-firestore API.priority: p2Moderately-important priority. Fix may not be included in next release.Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.Error or flaw in code with unintended results or allowing sub-optimal usage patterns.