10 Common Firebase Security Vulnerabilities and How to Fix Them
After scanning hundreds of Firebase applications, we've identified recurring security vulnerabilities that put user data at risk. This guide covers the 10 most common Firebase security issues and shows you exactly how to fix them.
1. World-Readable Realtime Database
The Vulnerability
The most critical issue we find: databases with .read: true in root rules, making all data publicly accessible.
Vulnerable code:
{
"rules": {
".read": true,
".write": "auth != null"
}
}Why it's dangerous: Anyone can download your entire database without authentication. User emails, personal data, and sensitive information are exposed.
The Fix
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}Better yet, restrict to user-specific data:
{
"rules": {
"users": {
"$uid": {
".read": "$uid === auth.uid",
".write": "$uid === auth.uid"
}
}
}
}How to Test
firescan > scan --unauthShould show "Permission denied" for sensitive paths.
2. Missing User Isolation in Firestore
The Vulnerability
Firestore rules that allow any authenticated user to read/write all documents.
Vulnerable code:
match /users/{userId} {
allow read, write: if request.auth != null;
}Impact: User A can read and modify User B's data.
The Fix
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}For shared collections with proper access control:
match /posts/{postId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == resource.data.authorId;
}3. Unprotected Cloud Functions
The Vulnerability
HTTP Cloud Functions with no authentication checks.
Vulnerable code:
exports.deleteUser = functions.https.onRequest((req, res) => {
const userId = req.body.userId;
admin.auth().deleteUser(userId);
res.send("User deleted");
});Impact: Anyone can call your functions and perform privileged operations.
The Fix
exports.deleteUser = functions.https.onCall(async (data, context) => {
// Verify authentication
if (!context.auth) {
throw new functions.https.HttpsError('unauthenticated',
'User must be authenticated');
}
// Verify authorization
const uid = context.auth.uid;
if (uid !== data.userId && !await isAdmin(uid)) {
throw new functions.https.HttpsError('permission-denied',
'Insufficient permissions');
}
await admin.auth().deleteUser(data.userId);
return { success: true };
});Use onCall instead of onRequest for automatic authentication handling.
4. Public Cloud Storage Buckets
The Vulnerability
Storage buckets allowing public read/write access.
Vulnerable code:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}Impact: Anyone can upload files to your bucket or download all stored files.
The Fix
service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/{allPaths=**} {
allow read, write: if request.auth.uid == userId;
}
match /public/{allPaths=**} {
allow read;
allow write: if request.auth != null && request.auth.token.admin == true;
}
}
}5. No Data Validation
The Vulnerability
Rules that don't validate data types or required fields.
Vulnerable code:
match /posts/{postId} {
allow write: if request.auth != null;
}Impact: Users can write arbitrary data, breaking your application or injecting malicious content.
The Fix
match /posts/{postId} {
allow write: if request.auth != null
&& request.resource.data.keys().hasAll(['title', 'content', 'authorId'])
&& request.resource.data.title is string
&& request.resource.data.title.size() > 0
&& request.resource.data.title.size() <= 200
&& request.resource.data.content is string
&& request.resource.data.authorId == request.auth.uid;
}6. Overly Permissive List Operations
The Vulnerability
Allowing users to list entire collections.
Vulnerable code:
match /users/{userId} {
allow read: if request.auth != null;
}Impact: Users can enumerate all documents in a collection, discovering other users, IDs, or sensitive paths.
The Fix
match /users/{userId} {
allow get: if request.auth != null && request.auth.uid == userId;
// No "list" permission granted
}Or restrict list operations:
match /users/{userId} {
allow list: if request.auth != null
&& request.query.limit <= 10
&& request.auth.token.admin == true;
}7. Missing Write Validation
The Vulnerability
Allowing users to modify fields they shouldn't.
Vulnerable code:
match /users/{userId} {
allow update: if request.auth.uid == userId;
}Impact: Users can set themselves as admin or modify critical fields.
The Fix
match /users/{userId} {
allow update: if request.auth.uid == userId
&& !request.resource.data.diff(resource.data).affectedKeys().hasAny(['role', 'isAdmin', 'credits']);
}Or whitelist allowed fields:
match /users/{userId} {
allow update: if request.auth.uid == userId
&& request.resource.data.diff(resource.data).affectedKeys().hasOnly(['displayName', 'photoURL', 'bio']);
}8. Timestamp Manipulation
The Vulnerability
Allowing users to set their own timestamps.
Vulnerable code:
match /posts/{postId} {
allow create: if request.auth != null
&& request.resource.data.authorId == request.auth.uid;
}Impact: Users can backdate or future-date content, manipulate sorting, or bypass time-based restrictions.
The Fix
match /posts/{postId} {
allow create: if request.auth != null
&& request.resource.data.authorId == request.auth.uid
&& request.resource.data.createdAt == request.time;
}9. Weak Query Security
The Vulnerability
Not restricting query parameters in rules.
Vulnerable code:
match /posts/{postId} {
allow list: if request.auth != null;
}Impact: Users can query all data without restrictions, bypassing intended access controls.
The Fix
match /posts/{postId} {
allow list: if request.auth != null
&& request.query.limit <= 20
&& request.query.orderBy == 'createdAt';
}10. Insecure Custom Claims
The Vulnerability
Setting custom claims based on client input.
Vulnerable code:
exports.setAdmin = functions.https.onCall(async (data, context) => {
if (data.isAdmin) {
await admin.auth().setCustomUserClaims(context.auth.uid, {
admin: true
});
}
});Impact: Any user can make themselves an admin.
The Fix
exports.setAdmin = functions.https.onCall(async (data, context) => {
// Verify caller is already an admin
if (!context.auth.token.admin) {
throw new functions.https.HttpsError('permission-denied');
}
// Additional verification
const targetUser = await admin.auth().getUser(data.targetUid);
if (!targetUser.email.endsWith('@company.com')) {
throw new functions.https.HttpsError('invalid-argument');
}
await admin.auth().setCustomUserClaims(data.targetUid, {
admin: true
});
});How to Find These Vulnerabilities
Manual Review
Review your security rules file by file, checking for:
- Public read/write access
- Missing user isolation
- No data validation
- Unrestricted queries
Automated Scanning with FireScan
FireScan automatically tests for these vulnerabilities:
# Install
go install github.com/JacobDavidAlcock/firescan/cmd/firescan@latest
# Configure
firescan
firescan > set projectID your-project
firescan > set apiKey AIza...
# Test unauthenticated access
firescan > scan --unauth
# Test authenticated access
firescan > auth --create-account
firescan > scan --allTesting Best Practices
- Test before deploying - Always test rules changes before production
- Test multiple authentication states - Unauthenticated, authenticated, admin
- Test edge cases - Empty values, special characters, maximum sizes
- Use automated tools - Catch issues humans miss
- Regular audits - Re-test periodically as your app evolves
Quick Security Checklist
- [ ] No world-readable databases
- [ ] User data isolated by UID
- [ ] Cloud Functions require authentication
- [ ] Storage rules restrict access
- [ ] Data validation on all writes
- [ ] List operations restricted
- [ ] Critical fields protected from modification
- [ ] Timestamps server-controlled
- [ ] Query parameters validated
- [ ] Custom claims properly secured
Next Steps
- Test your Firebase app with FireScan
- Learn about Firebase security testing
- View the complete security rules reference
Don't let these common vulnerabilities compromise your Firebase application. Test regularly and fix issues before attackers find them.
Need help securing your Firebase app? Get a professional security assessment or support FireScan development.
