Description
The referral update rule in firestore.rules (RULE 3) allows any authenticated user to write to any other user's document as long as they increment referralPoints by exactly 100 and keep all other point categories unchanged:
// RULE 3
allow update: if isAuthenticated()
&& request.auth.uid != uid // caller must not be the owner
&& request.resource.data.points.referralPoints == resource.data.points.referralPoints + 100
&& request.resource.data.points.totalPoints == resource.data.points.totalPoints + 100
&& request.resource.data.points.gitRankPoints == resource.data.points.gitRankPoints
&& request.resource.data.points.codingVersePoints == resource.data.points.codingVersePoints
&& request.resource.data.points.streakPoints == resource.data.points.streakPoints;
This rule does not verify:
-
That the referred user was actually referred by the target user -- Any logged-in user can choose any other user's UID and trigger this rule, granting the target 100 referral points without any actual referral relationship.
-
That the referral hasn't already been applied -- The rule can be triggered repeatedly from the same caller against the same target, each time adding another 100 referral points. A user could inflate another user's score indefinitely.
-
That the caller is completing their own onboarding -- The referral trigger should only be permitted during the referring user's first onboarding, not at any arbitrary time.
Steps to Reproduce
- Sign in as User A.
- Identify any other user's UID (User B) by reading their public profile.
- Directly write to Firestore
users/userB_uid with points.referralPoints = current + 100 and points.totalPoints = current + 100.
- Observe that the write succeeds because RULE 3 is satisfied.
- Repeat step 3 multiple times and watch User B's referral points increase by 100 on each iteration.
Expected Behavior
The referral point write should only succeed when:
- The
referrals/{targetUid} document confirms that request.auth.uid is listed as a valid, unprocessed referred user.
- The operation is idempotent (subsequent attempts by the same caller are rejected).
Actual Behavior
Any authenticated user can grant any other user unlimited referral points by making repeated writes that each satisfy the +100 increment check.
Affected Code
firestore.rules, RULE 3:
allow update: if isAuthenticated()
&& request.auth.uid != uid // only prevents self-referral
&& request.resource.data.points.referralPoints == resource.data.points.referralPoints + 100
... // no referral relationship check
Suggested Fix
Cross-reference the referrals collection to verify the relationship before allowing the point update:
allow update: if isAuthenticated()
&& request.auth.uid != uid
&& request.resource.data.points.referralPoints == resource.data.points.referralPoints + 100
&& request.resource.data.points.totalPoints == resource.data.points.totalPoints + 100
&& request.resource.data.points.gitRankPoints == resource.data.points.gitRankPoints
&& request.resource.data.points.codingVersePoints == resource.data.points.codingVersePoints
&& request.resource.data.points.streakPoints == resource.data.points.streakPoints
// Verify the referral relationship exists and the caller is listed
&& exists(/databases/$(database)/documents/referrals/$(uid))
&& request.auth.uid in get(/databases/$(database)/documents/referrals/$(uid)).data.usedBy;
Contribution Guidelines
I would like to work on this under NSoC '26. @indresh404, could you please assign/ this issue to me?
Description
The referral update rule in
firestore.rules(RULE 3) allows any authenticated user to write to any other user's document as long as they incrementreferralPointsby exactly 100 and keep all other point categories unchanged:This rule does not verify:
That the referred user was actually referred by the target user -- Any logged-in user can choose any other user's UID and trigger this rule, granting the target 100 referral points without any actual referral relationship.
That the referral hasn't already been applied -- The rule can be triggered repeatedly from the same caller against the same target, each time adding another 100 referral points. A user could inflate another user's score indefinitely.
That the caller is completing their own onboarding -- The referral trigger should only be permitted during the referring user's first onboarding, not at any arbitrary time.
Steps to Reproduce
users/userB_uidwithpoints.referralPoints = current + 100andpoints.totalPoints = current + 100.Expected Behavior
The referral point write should only succeed when:
referrals/{targetUid}document confirms thatrequest.auth.uidis listed as a valid, unprocessed referred user.Actual Behavior
Any authenticated user can grant any other user unlimited referral points by making repeated writes that each satisfy the +100 increment check.
Affected Code
firestore.rules, RULE 3:Suggested Fix
Cross-reference the
referralscollection to verify the relationship before allowing the point update:Contribution Guidelines
I would like to work on this under NSoC '26. @indresh404, could you please assign/ this issue to me?