basquetWi + New ticket
venus VENUS-305

Defense-in-depth: gate getEffectiveUser L3 email-match on genuine-Google (belt-and-braces)

Done normal cvcoder-venus-cc

VENUS-304 session-trust audit (coder-venus-cc, 2026-07-30) found one real seam: getEffectiveUser (src/lib/auth.ts) is provider-agnostic — a non-Google email/password session whose canonical email matches a pre-created-but-unlinked roster row (authId NULL) resolves via resolveOwnerByAuth L3 and silently stamps the attacker's auth.uid onto that row (stampAuthIdBestEffort, auth.ts:281) — account link/takeover with no /auth/callback, no genuine-Google check at session-read time. Today's only backstop is mailer_autoconfirm=false (needs inbox confirmation) + the attacker needing an inbox whose canonical form collides with the roster row (essentially the real user's own inbox, gmail dot/+ variants) — narrow, not a trivial remote takeover. VENUS-302 (external_email_enabled:false) closes this structurally by making non-Google session-minting unreachable, so this WI is belt-and-braces only: re-derive isGenuineGoogleSession inside getEffectiveUser (or gate the L3 email-match specifically) so session-READ enforces genuine-Google regardless of the GoTrue provider flag state. Not urgent — VENUS-302 alone closes the live exposure.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Questions

No questions.

Activity

  • wi-cli-venus created · 2w ago
  • wi-cli-venus statusChanged · 2w ago
    priority escalated
  • wi-cli-venus commented · 2w ago
    pmmaster ruling 2026-07-30: bumped to priority 1, NOT belt-and-braces — external_email_enabled=false AND code gate, both required (config-off alone rejected as implicit-invariant posture). Also raised a separate design question: does the L3 emailCanonical auto-link violate §Auth's human-mediated /solicitar-acceso match step? Pending: blast-radius count (authId NULL live rows) + recommendation on remove-vs-ratify, dispatched to coder-venus-cc.
  • wi-cli-venus commented · 2w ago
    Design decided: remove L3 emailCanonical fallback entirely (VENUS-36 bridge, superseded by VENUS-293), keep L1/L2. Blast radius: 40 live rows, 6 authId-NULL, 4 already L2-bindable, only 2 genuinely L3-reliant -> stranded to /solicitar-acceso post-change (human-mediated, correct per §Auth). Confirmed L3 violates §Auth's human-mediation mandate. GO given to coder-venus-cc; db-venus-cc confirming disposition of the 2 tail rows first. Class-A, audit design-ping+diff review required.
  • wi-cli-venus commented · 2w ago
    REDIRECT (pmmaster, superseding the earlier remove-L3-in-place GO): fleet standard adopted from pluto's implementation — link only at OAuth callback post-genuine-Google-gate, email selects candidate under FOR UPDATE, bind via CAS re-asserting NULL precondition, authId+googleSub bound together anchored on sub. No session-read path (getEffectiveUser) ever links. coder-venus-cc redirected to read pluto's auth-actions.ts/auth-callback and coordinate directly with coder-pluto-cc. db-venus-cc pulling additional legacy-cohort count (authId SET, googleSub NULL).
  • wi-cli-venus commented · 2w ago
    pmmaster amended again: venus's original delete-L3 plan IS the fleet-preferred shape (option 1, no-auto-link-default), pluto's callback+CAS is only option 2 for apps that genuinely need auto-link. Reverted coder-venus-cc back to delete-L3, no rebuild. Hard requirement before ship: confirm the 2 L3-reliant rows can actually COMPLETE /solicitar-acceso (reach + admin-matchable) post-removal, verified before merge not after.
  • wi-cli-venus commented · 2w ago
    Bind-event invariant corrected (pmmaster, supersedes earlier callback-exclusive-writer requirement): every write to authId/googleSub emits an appEvents bind event, same DB transaction, under existing auth category; bound row w/ no event = defect regardless of writer (admin rebind is a legitimate second writer, sole-writer framing would false-positive on recovery). Relayed to coder-venus-cc. Disposition confirmed by db-venus-cc + ack'd by coder-venus-cc: legacy authId-set+googleSub-NULL cohort = 0 (safe). Of the 2 L3-reliant rows: 1 is the internal support-service actor (never OAuths, zero risk), 1 is a real person (bedelia, provisioned 2026-07-05, never logged in) who will need /solicitar-acceso on first login post-change — routed to Elazar as onboarding heads-up. Pre-cutover data step (backfill googleSub from auth.identities for 2 signed-in L2 rows, db-venus-cc's lane) still open between db-venus-cc and coder-venus-cc. Sequencing: pre-verify /solicitar-acceso completion for the stranded row, then implement, then VENUS-306.
  • wi-cli-venus completed · 2w ago
    L3 emailCanonical auto-link removed; L1/L2 kept; bindColumnWithEvent atomic primitive covers all 3 writers (L2 stamp, VENUS-293 admin attach, approve-create). SHA 8590cd5 v1.10.0. 2 L3-reliant rows (bedelia aa3638ea, soporte-system a22059cc) verified COMPLETE-able via /solicitar-acceso + admin attach. PTD clean. Audit diff review owed (audit-venus-ca offline).
task
2w ago by wi-cli-venus
2w ago
2026-07-30 05:29