Firebase Security Vulnerability: FBR-LOGIC-004¶
Name: Insecure Delete Operation Leading to Orphaned Data
Applicable Services: Cloud Firestore
Description¶
Note
This data integrity vulnerability occurs when security rules permit a delete operation on a document without ensuring that related, dependent data in other documents is also handled. - The Technical Flaw: The security rule allows a client-side delete
on a document (e.g., /users/{userId}
) without considering that other documents (e.g., in a posts
collection) hold a reference to it. Firestore does not enforce referential integrity, so it won't automatically clean up these dependent references. - Intended Behavior: Deletions of documents that are referenced by other parts of the database should be handled by a trusted server process (like a Cloud Function) that can perform a "cascading delete," ensuring all related data is removed atomically. - The Risk: Allowing direct client-side deletes can lead to an inconsistent data state where some records point to non-existent documents. This "orphaned" data can cause application crashes, UI errors, and a poor user experience.
Impact¶
Potential Consequences
The severity of this vulnerability is a warning. Exploiting it can lead to: * Application Errors - The application may crash or enter an error state when it tries to look up an orphaned reference that no longer points to an existing document. * Data Inconsistency - The database is left in an inconsistent state, making data management and future development more difficult.
* Poor User Experience - Users may see broken UIs, error messages, or experience app crashes, leading to a loss of trust.
Example Attack Scenarios¶
Exploit Scenario: Deleting a User and Orphaning Their Posts
- The Vulnerable Rule: The following Firestore rule allows a user to delete their own profile document, but there's no mechanism to clean up the posts they've created.
// VULNERABLE: Allows a user to delete their own profile, // but does not handle the user's posts. service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow delete: if request.auth.uid == userId; } match /posts/{postId} { // For this example, anyone can read posts allow read: if true; } } }
- Attacker's Goal: This isn't a malicious attack, but a standard user action that reveals a flaw. A user wants to delete their account.
- The Exploit: The user triggers a delete operation from the client-side application. Their profile document at
/users/user-abc
is successfully deleted.// A standard client-side operation that triggers the vulnerability. // A user with UID "user-abc" deletes their own profile. db.collection("users").doc("user-abc").delete .then(() => { console.log("User profile successfully deleted!"); }) .catch((error) => { console.error("Error removing document: ", error); });
- Outcome: The user's profile is gone, but all their documents in the
posts
collection, which containauthorId: "user-abc"
, remain. When the application tries to load one of these posts and fetch the author's details, the lookup for/users/user-abc
fails, leading to application errors or a broken UI.
Mitigation¶
The vulnerability is resolved by disallowing direct client-side deletes on documents with dependencies. Instead, deletions should be handled by a trusted server process, like a Cloud Function, which can perform a cascading delete.
// SECURE: Blocks direct client-side deletes, forcing them
// to be handled by a trusted server process.
match /users/{userId} {
// Create, read, and update might be allowed.
allow create, read, update: if request.auth.uid == userId;
// Direct deletes are explicitly forbidden.
allow delete: if false;
}
Best Practice
The most robust solution is to handle deletions via a server-side environment (like a Cloud Function) that performs atomic, cascading deletes using a batched write. With the secure rule in place, the client application would call a Cloud Function (e.g., deleteUserAccount
). This function would then use the Firebase Admin SDK to perform a batched write that deletes the user's profile document and all their posts in a single, atomic operation, preventing any data from being orphaned.