HOW TO SECURE FIREBASE - SECURITY GUIDE | VIBEEVAL
Critical: Disable Test Mode
Test mode rules — allow read, write: if request.time < timestamp.date(YYYY, M, D); — allow anyone to read and write all data until the date passes. They are the most common Firebase security mistake, and the date almost always arrives after launch when nobody is watching. Replace with production rules before deploying.
Security Checklist
1. Disable test-mode rules
Open firestore.rules and storage.rules. Delete every allow read, write: if request.time < timestamp.date(...) and every allow read, write: if true. Replace with predicates keyed on request.auth and the resource’s owner field. Verify with the Firebase Scanner.
2. Write Security Rules per service
Different services have different rule files:
// firestore.rules
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
match /posts/{postId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == resource.data.author_id;
}
// storage.rules
match /users/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024;
}
// database.rules.json (Realtime DB)
{ "rules": { "users": { "$uid": { ".read": "auth.uid === $uid", ".write": "auth.uid === $uid" } } } }
Each service’s rules are independent — locking down Firestore doesn’t lock down Storage.
3. Test rules with the Firebase Emulator
firebase emulators:start --only firestore then write tests with @firebase/rules-unit-testing covering: anonymous access (should fail), wrong-user access (should fail), correct-user access (should succeed), admin access (should succeed). The emulator is the only way to test rules locally before they go live.
4. Understand API key visibility
Firebase web API keys are public-by-design — they identify the project, not authenticate it. Don’t worry about the key being in your bundle; do worry about restricting what the key can do. In Google Cloud → Credentials → [API key] → Restrictions: limit to specific HTTP referrers and specific APIs.
5. Enable App Check
In Firebase Console → App Check: register the app with reCAPTCHA Enterprise (web) or Play Integrity (Android) / DeviceCheck (iOS). Enable enforcement for Firestore, Storage, Functions, and Realtime Database. App Check is the difference between “anyone can hit your Firestore from a script” and “only requests from your real app are accepted.”
6. Configure Firebase Authentication
Authentication → Sign-in method: enable only providers you use (disable Anonymous unless required). Authentication → Settings → User actions → Enable account creation: gate self-signup if your app is invite-only. Authentication → Templates → Email verification: confirm enabled, action URL points to production.
7. Audit Cloud Functions
For each callable function:
exports.foo = functions.https.onCall((data, context) => {
if (!context.auth) throw new functions.https.HttpsError('unauthenticated', 'Login required');
// ...
});
For each HTTP function: verify the ID token (admin.auth().verifyIdToken(req.headers.authorization)), validate the body, set CORS to your origin only.
8. Enable Cloud Audit Logs
Google Cloud → IAM → Audit Logs: enable Data Read and Data Write for Firestore and Storage. Default is Admin only — meaning user-data reads aren’t logged, and you can’t investigate an incident you can’t see.
9. Configure Storage rules
Default Firebase Storage rules let any authenticated user read and write any path. Lock to the per-user folder pattern (see step 2) and add a max-size predicate. The recurring incident shape is “image upload” that allows arbitrary file types, and “user A’s avatar” reachable by anyone with the user ID.
10. Review Firebase Hosting config
In firebase.json, configure security headers in hosting.headers:
"headers": [{
"source": "**",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "X-Frame-Options", "value": "DENY" }
]
}]
Verify with the Security Headers Checker.
11. Enable rate limiting on Cloud Functions
Cloud Functions don’t rate-limit by default. For HTTP functions, front them with a load balancer + Cloud Armor for rate limiting and WAF rules. For callable functions, implement rate limiting in the function: track per-user invocation counts in Firestore and reject when over.
12. Move secrets to Secret Manager
Stop hardcoding Stripe / SendGrid / OpenAI keys in functions/src/. firebase functions:secrets:set STRIPE_SECRET_KEY then process.env.STRIPE_SECRET_KEY from inside the function. Secrets are never logged in deploy output.
13. Set up Firebase Performance + Crashlytics
Enable Crashlytics for client-side errors and Performance Monitoring for latency. Errors include source maps if you uploaded them — useful for debugging, sensitive in the wrong hands. Restrict access in Firebase Console → IAM.
14. Audit Firestore indexes for cost
Indexes don’t directly affect security but a missing composite index means a query gets slow, which means an attacker can DoS by triggering it. Define every composite index your app needs in firestore.indexes.json.
15. Run a Security Rules scan
The Firebase Scanner audits firestore.rules and storage.rules for the recurring AI-generated patterns: wildcard rules, if request.auth != null (which lets any logged-in user read any data), and missing size predicates on Storage.
Common Vulnerabilities in Firebase Apps
Test Mode Left in Production
The if request.time < timestamp.date(...) clause that ships with new Firebase projects. The expiry usually arrives after launch.
if request.auth != null Without Ownership
A common AI-generated rule. Allows any logged-in user to read any document. Should be request.auth.uid == resource.data.user_id (or equivalent ownership predicate).
Storage Open to Authenticated Users
Default Storage rule lets any authenticated user read/write any path. Per-user folder + size predicate is the minimum.
Cloud Functions Without Auth
Callable functions deployed without context.auth check are reachable from anywhere. The bug ships when an AI tool wraps an admin action as a callable function for convenience.
Related Resources
Firebase Scanner
Free scanner for firestore.rules and storage.rules.
Free Self-Audit Suite
Five free scanners.
Vibe Coding Security Risk Guide
Full risk catalogue.
Firebase Studio Guide
Securing apps generated by Gemini in Firebase Studio.
Test Your Security Rules Automatically
VibeEval scans your live Firebase project’s rules and probes Cloud Function endpoints. Findings ship as paste-ready rule snippets and fix prompts.
SCAN YOUR APP
14-day trial. No card. Results in under 60 seconds.