p0-h2-login-timing

donetype/backlogpriority/p0severity/hightopic/authtopic/enumeration

p0 · H2 · Login timing leaks email existence

TL;DR

DUMMY_HASH + bcrypt.compare on user-not-found and inactive paths in Auth.js authorize() (src/auth.ts). Vitest guard in loginTimingEqualization.test.ts. Shipped as Phase D step 1.

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

Shipped (app repo)

  • DUMMY_HASH constant; compare before InvalidCredentials when !user || !user.isActive
  • No user.save() on not-found path
  • src/lib/auth/loginTimingEqualization.test.ts

Spun out

None (optional manual 20× curl timing check is ops/QA, not tracked separately).

Related

  • [[Projects/personal-finance-notion/backlog/done/p0-authjs-phase-d-pre-launch-hardening|Phase D]]
  • [[Projects/personal-finance-notion/backlog/p1-signup-timing-equalization|p1 · Signup timing]] — separate surface