Flow docs updated (11 files): - Delivery Confirmation: reversed actor roles (buyer generates, seller verifies), fixed endpoint paths (/delivery-code/generate, /delivery-code/verify) - Passkey (WebAuthn): removed stub/simulated-key claims; real @simplewebauthn/server attestation is implemented; refresh tokens are persisted - Dispute: corrected resolve schema (action enum), removed non-existent statuses, documented security gaps (no role guards on status/resolve/assign), route shadowing, all socket events are TODO stubs - Seller Offer: corrected all endpoint paths, removed 'active' status, documented withdraw dead code, missing seller history page, select-offer notification gap - Notification: corrected mark-all-read method+path, fixed GET /:id broken lookup, added unread-count-update socket event - Authentication: corrected rate limiter (counts all attempts), axios 403 not handled, deleteAccount wrong endpoint bug, changePassword no UI - Password Reset: corrected 6-digit code (not 8), documented no-complexity gap on reset-with-code vs token reset - Payment Flow DePay: /create→/save, removed phantom sub-routes, SIM_ bypass risk, PaymentProvider type gap, getProviderIntentEndpoint routing bug - Payment Flow SHKeeper: removed phantom polling endpoint, fixed release/refund paths - Purchase Request: added pending_payment/active statuses, fixed sellers/attachments endpoints, corrected socket events, PUT→PATCH bug - Escrow: documented dispute resolve does not touch escrow, route shadowing, confirm-delivery auth gap Issues created (35 files in Issues/): - 9 security issues (critical) including: dispute privilege escalation ×4, unauthenticated payment/scanner endpoints ×2, SIM_ production bypass, confirm-delivery ownership gap - 26 additional major/critical bugs covering broken endpoints, missing features, data integrity gaps, and frontend-backend mismatches Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1.6 KiB
issue, title, severity, domain, labels, status, created, source
| issue | title | severity | domain | labels | status | created | source | ||
|---|---|---|---|---|---|---|---|---|---|
| 022 | Login rate limiter counts all attempts (not just failures) — users can be locked out after correct logins | major | auth |
|
open | 2026-05-29 | Doc vs Code Audit 2026-05-29 |
🟠 Login rate limiter counts all attempts (not just failures) — users can be locked out after correct logins
Severity: major Domain: auth Labels: backend, bug
Description
rateLimitService.checkLoginAttempts() calls checkLimit() which calls redisService.incr — incrementing the counter on every invocation, before password comparison. The counter is only reset after a full successful login (password verified + session created).
With the limit at 5 attempts/15 min, a user who makes 4 correct logins in quick succession (e.g., testing on multiple devices) followed by 1 wrong password will be locked out immediately, even though they never "failed" 5 times in the intended sense.
Current Behavior
5 total login attempts within 15 minutes (any combination of correct/incorrect passwords) triggers 429 TOO_MANY_ATTEMPTS.
Expected Behavior
The counter should only increment on failed password comparison, not on every attempt. Alternatively, the behaviour should be clearly documented so UX can warn users appropriately.
Affected Files
backend/src/services/auth/rateLimitService.ts—checkLoginAttempts/checkLimit— counter increment should move to after password comparison inauthController.ts
References
- Doc vs Code Audit Report — Finding M3