Skip to content

AUTH-001A — Reject unverified targets at existing role-grant endpoints #98

Closed

Description

@daliu

Problem

The existing admin callable and legacy membership-sync endpoint grant Firebase custom claims by matching an email address, but neither checks the authoritative Firebase Auth userRecord.emailVerified value. An attacker can pre-register a known member address and receive membership access when that address is imported.

Security invariant

Promotion to member or admin is allowed only when Firebase Auth reports userRecord.emailVerified === true. Request fields and Firestore profile mirrors never prove verification. Demotion to unverified remains allowed so operators can remove access safely.

Atomic scope

  • Add one small pure role-grant policy helper.
  • Apply it immediately after authoritative Auth lookup and before any claim or Firestore write in setMemberRole.
  • Apply it before any claim or Firestore write in each updateMemberRole batch item.
  • Preserve existing authorization, App Check, batch bounds, admin-grant exclusion, and self-demotion protection.
  • Return a bounded, non-sensitive failure for an unverified target.
  • Add positive, negative, forged-field, no-side-effect, mixed-batch, and demotion tests using synthetic identities only.

Explicitly out of scope

  • Firestore Rules or privileged server guards.
  • Email-verification profile mirrors or verification triggers.
  • Existing-claim remediation, token revocation, propagation, audit schema, MFA, or capabilities.
  • Replacement of the legacy static API-key endpoint; that remains AUTH-002.
  • Any production identity, provider, or configuration change.

Acceptance criteria

  • Unverified or missing verification state cannot receive member through either endpoint.
  • Unverified target cannot receive admin through the admin callable.
  • Verified targets retain current authorized promotion behavior.
  • A forged request emailVerified value is ignored.
  • Denial happens before setCustomUserClaims and before Firestore profile writes.
  • Demotion to unverified still succeeds for an unverified target.
  • Existing admin self-demotion protection remains intact.
  • Mixed bulk input promotes verified targets only and reports the rejected target without aborting successful items.
  • Bulk endpoint still cannot grant admin.
  • Focused and full Functions tests, lint, Rules tests, diagnostic frontend build, and diff check pass.

Dependencies and file ownership

  • Stable parent: AUTH-001 in GITHUB_ISSUES.md; coordination epic: COMMUNITY-EPIC — Unified member access and community integrations #79.
  • Hard dependencies: none. SEC-001 is recommended for the remaining parent work but is not required for this endpoint-only invariant.
  • Expected files: functions/setMemberRole.js, functions/updatemembers.js, new functions/roleGrantPolicy.js, new functions/roleGrantPolicy.test.js.
  • Do not touch the parallel callback/emulator, Rules, Stripe/payment, package, or root-documentation worktree clusters.

Claim protocol

Do not edit until this issue is assigned and a timestamped CLAIMED comment names the agent and branch. Earliest valid claim wins.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:authAuthentication and authorization
    area:firebaseFirebase services and data
    size:SSmall focused issue
    status:readyDependencies complete and ready to claim
    on Jul 12, 2026
  2. self-assigned this
    on Jul 12, 2026
  3. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    CLAIMED by Codex agent /root at 2026-07-12T20:47:24Z; branch codex/issue-98-verified-role-grants

  4. added
    status:in-progressClaimed and actively being implemented
    and removed
    status:readyDependencies complete and ready to claim
    on Jul 12, 2026
  5. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    Implementation is published in #107 from the claimed branch.

    Evidence:

    • test-first regression reproduced distinct bulk failure details for unverified versus nonexistent synthetic targets
    • final policy requires authoritative Firebase Auth emailVerified === true before member/admin claim or profile writes
    • bulk failures are now bounded and indistinguishable; verified mixed-batch items still succeed
    • focused role-grant tests: 10/10 passed
    • full Functions tests: 3 suites / 17 tests passed
    • full Functions lint, Rules emulator tests (4 suites / 97 tests), diagnostic frontend build, and diff check passed
    • two independent read-only reviews approved the final diff; the security review finding about raw bulk provider errors was fixed and re-reviewed

    No production identity/provider configuration was read or changed. Deployment status will be reported separately after merge checks complete.

  6. added a commit that references this issue on Jul 12, 2026
    ce22c11
  7. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    Completed in merged PR #107 (merge commit ce22c11).

    Post-merge verification:

    Production deployment authority/configuration was explicitly out of scope for #98 and is tracked by CI-001 #105. Closing this atomic code issue as completed with that handoff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:authAuthentication and authorizationarea:firebaseFirebase services and datapriority:P0Launch blocker or urgent security risksize:SSmall focused issuetype:securitySecurity or privacy boundary

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions