p0-c3-signup-enumeration

donetype/backlogpriority/p0severity/criticaltopic/authtopic/enumeration

p0 · C3 · Signup leaks email existence

TL;DR

Full fix shipped in Phase B (signup() in src/lib/actions/auth.ts): identical success shape and “check your inbox” UI for new, existing unverified, and existing verified emails; silent emails per branch. Timing equalization and duplicate-signup E2E spun out.

Status: done (2026-05-24) · Source: [[Projects/personal-finance-notion/context/audit-2026-05-17-auth|Auth audit 2026-05-17 §C3]]

Shipped (app repo)

  • signup() returns { success: true, awaitingVerification: true } for all non-validation outcomes
  • Verified duplicate → account-exists-already email; unverified → re-send verify; new → create + verify
  • Signup UI always shows check-inbox state on success (src/app/(auth)/signup/page.tsx)
  • Internal errors swallowed → still return generic success (enumeration-safe)

Implementation checklist

  • [x] No verbatim “Email already exists” on signup path
  • [x] Same JSON success shape for new vs existing email
  • [x] Appropriate email sent per branch (verify vs account-exists)
  • [x] No session cookie on signup

Spun out (not blocking “done”)

  • [[Projects/personal-finance-notion/backlog/p1-signup-timing-equalization|p1 · Signup timing equalization]] — response-time side channel (~5ms audit target)
  • [[Projects/personal-finance-notion/backlog/p2-signup-enumeration-e2e|p2 · Signup enumeration E2E]] — existing vs new email → identical UI assertion

Related

  • [[Projects/personal-finance-notion/backlog/done/p0-h2-login-timing|H2 · Login timing]]