p1-password-reset-rate-limits
readytype/backlogpriority/p1severity/mediumtopic/authtopic/rate-limit
p1 ยท Password reset rate limits (3/h email + IP)
TL;DR
Replace the current generalRateLimiter (10/min per email only) on requestPasswordReset with audit-spec limits: 3 requests/hour per email and 5 requests/hour per IP, without breaking enumeration-safe generic success responses.
Description
- Problem:
src/lib/actions/passwordReset.ts uses generalRateLimiter (10 attempts / 1 minute, email key only). The original C1 audit called for 3/h per email and 5/h per IP to limit abuse and email bombing.
- Context: Core reset flow is shipped ([[Projects/personal-finance-notion/backlog/done/p0-c1-password-reset|C1 done]]). This is hardening, not a missing feature.
Acceptance criteria
- [ ] Dedicated limiter(s) or key namespace:
password-reset:email:<addr> โ max 3 / hour
- [ ] IP dimension: derive client IP from headers in the server action (or shared helper used by other auth flows); key
password-reset:ip:<ip> โ max 5 / hour
- [ ] When either limit trips,
requestPasswordReset still returns { success: true } (no enumeration leak)
- [ ] Unit or integration test for limit behavior (optional but preferred)
Implications
If skipped
- Attackers can trigger high-volume reset emails to a victim address (harassment) or burn Resend quota. Enumeration remains fixed; abuse and cost risk remain.
Why this priority
- p1 โ abuse and email-bombing risk after happy-path reset works; not p0 because recovery flow is already shippable.
When shipped
- Reset requests align with audit abuse model; complements enumeration-safe responses from C1.
Dependencies
- None. Shares
RateLimitModel / rateLimiter.ts with login/signup limiters.
Links
- App repo:
src/lib/actions/passwordReset.ts, src/lib/utils/rateLimiter.ts