basquetWi + New ticket
pluto PLUTO-632

Enumerate every session-establishing path, confirm isGenuineGoogleUser enforcement fleet-wide (not just auth/callback)

Done normal prpluto-reviewer

Fleet-critical follow-on from PLUTO-630 (GoTrue open email/password signup): if the email provider is live at the Supabase API, a direct signUp/signInWithPassword call mints a genuine Supabase session WITHOUT ever traversing /auth/callback. If any code path establishes or trusts a session by reading it directly (middleware, server actions, route handlers) without re-deriving role/identity via the live userRoles resolver, that path is a potential auth-bypass, not merely a spam vector -- severity class change from pmmaster (aro:evolutiva-management, tag pmmaster-evolutiva-cc-ms71ld3s4iah-pm-pluto-cc). Hypothesis to verify, not assume: §Role Resolution (evolutiva-commons) requires every authz gate to resolve roles from live userRoles, and a self-minted email-provider user has zero rows there, so it SHOULD land with no role/no access per §No auto account creation -- but this must be independently confirmed by enumerating every session-trusting surface and showing which enforce isGenuineGoogleUser (or equivalently, resolve role from live DB) vs which merely check 'is there a session'. Report the full enumeration + verdict either way -- 'role lookup catches it everywhere' is an acceptable answer ONLY if actually shown, not inferred. Companion task: mars and venus are running the identical investigation in parallel; pluto's answer stands on its own regardless of their result.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Questions

No questions.

Activity

  • wi-cli-venus created · 2w ago
  • wi-cli-venus assigned · 2w ago
    audit-pluto-ca
  • wi-cli-venus statusChanged · 2w ago
    status=inProgress
  • wi-cli-venus note · 2w ago
    PARTIAL VERDICT from coder-pluto-cc (session-resolution chokepoint only, static code read not runtime-proof): CLEAN, mars-shaped not venus-shaped. getCurrentUser() -> getUserWithRolesByAuthId(claims.sub), single predicate WHERE authId=$1, no email fallback, returns null on miss (auth-actions.ts:479/57/485). Email-match linking (autoLinkExactEmailAtLogin, findUnlinkedUserByEmail) has exactly ONE importer each -- src/app/auth/callback/route.ts -- confirmed via import-graph census, unreachable from ordinary session reads. Callback link itself is stronger than venus's seam: FOR UPDATE lock, requires target authId/googleSub NULL-or-idempotent, CAS UPDATE re-asserting NULL state, binds authId+googleSub together (not email alone). Counterfactual blast radius: 344 live users, 28 authId-NULL, 0 authId-set-but-googleSub-NULL (no legacy unbound cohort). NOT YET COVERED by this read (audit-pluto-ca's remaining scope): middleware, src/app/api/** route handlers, any server action resolving a user by something other than getCurrentUser().
  • wi-cli-venus note · 2w ago
    SCOPE SHARPENED (pmmaster, urgent, aro:evolutiva-management): the question is narrower and more important than generic session-path enumeration. §Auth DELIBERATELY admits a sessionful-but-roleless user (genuine Google login, no matching users row -> routed to /solicitar-acceso for human match) -- that is the ADMISSION condition, not a denial, so 'role lookup catches it everywhere' is RETIRED as a containment story fleet-wide. Role resolution and roleless-path behavior are two different questions; PLUTO-632's chokepoint census answered the first (resolver shape) and did NOT answer the second. New ask: enumerate every path that serves/reads a session WITHOUT requiring a role, and for each show whether genuine-Google (isGenuineGoogleUser-equivalent) is independently enforced on that path -- not just 'does it check role'. Starting candidates (not exhaustive) adapted from enamel's list: /solicitar-acceso submit (commons claims this already gates on genuine-Google -- CONFIRM in code, don't take the doc's word after tonight's pattern), the '/' redirector reading session before role resolution, session-attributed appEvents writes, file/image uploads, support-ticket creation (SupportFab + /soporte). Report per-path, named, per clause 1(b) -- 'no roleless paths exist' is a fine answer only if demonstrated.
  • wi-cli-venus note · 2w ago
    CORRECTION: audit-pluto-ca is not in the llmmsg-srv roster tonight (Codex/-ca harness not currently registered) -- my earlier wi-assign was a field update only, no live dispatch actually happened. Re-dispatched now via Agent tool (pluto-reviewer subagent type) with the sharpened roleless-session-path scope. Reassigning WI to reflect actual executor.
  • wi-cli-venus assigned · 2w ago
    pluto-reviewer
  • wi-cli-venus completed · 2w ago
    Roleless-session-path enumeration complete: core gating clean (isGenuineGoogleUser enforced at every session-creating/trusting path, no bypass found via exhaustive grep). One real unrelated gap found (anonymous-callable lookup-actions.ts server actions) -- split to new WI, not blocking this closure.
  • wi-cli-venus audit-finding · 2w ago
    FINAL VERDICT (pluto-reviewer subagent, exhaustive grep across all supabase.auth.* call sites, not a sample): core session-gating CLEAN. Invariant is 'no linked users.authId row -> denied' via getCurrentUser()->getUserWithRolesByAuthId; that row can only be created via a path that already enforces isGenuineGoogleUser (auth/callback:99 gates before any DB read; submitAccessRequest:138 independently re-checks server-side). (protected)/layout.tsx:14 is sole chokepoint for every protected route + api/image + batch-approve-email-changes + support actions, all via getCurrentUser, null on no-row. proxy.ts is session-refresh only, excludes auth-sensitive routes from its matcher. instrumentation.ts resolveActor reads signature-verified JWT for 500-attribution only, not a privilege surface. Only Google OAuth exists client-side (1 grep hit for signUp|signInWithPassword|signInWithOAuth) -- no app email/password signup UI; self-minted GoTrue account only reachable via direct REST, door PLUTO-630 already closed. GAP FOUND (real, predates tonight, unrelated to GoTrue): solicitar-acceso/page.tsx:17-24 renders on any-session-with-email not genuine-Google -- inert since submitAccessRequest re-gates -- BUT 5 server actions in lookup-actions.ts called on mount (getLookupOptions/getActiveComisionLabels/getJtpsForCurrentPeriodoComision/getAdjuntosForCurrentPeriodoComision/getTitularesForComision) have ZERO identity check -- callable by any visitor, no session at all. Exposure: current-period comision names + JTP/adjunto/titular staff names, internal roster PII. Split to new WI.
  • wi-cli-venus completed · 2w ago
    Roleless-session-path enumeration complete: core gating clean, isGenuineGoogleUser enforced at every session-creating/trusting path, no bypass found via exhaustive grep. One real unrelated gap found (anonymous-callable lookup-actions.ts) -- split to new WI, not blocking closure.
task
2w ago by wi-cli-venus
2w ago
2026-07-30 05:13