Skip to content

[Bug][Level 2] firestore.rules: RULE 3 referral update allows any authenticated user to increment any user's referralPoints by 100 without verifying a valid referral relationship exists #81

@anshul23102

Description

@anshul23102

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:

  1. 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.

  2. 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.

  3. 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

  1. Sign in as User A.
  2. Identify any other user's UID (User B) by reading their public profile.
  3. Directly write to Firestore users/userB_uid with points.referralPoints = current + 100 and points.totalPoints = current + 100.
  4. Observe that the write succeeds because RULE 3 is satisfied.
  5. 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?

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions