fix(19): WR-06 stop sliding the rate-limit cooldown window on rejected attempts
This commit is contained in:
@@ -135,9 +135,14 @@ localAuthRouter.post('/local/login', zValidator('json', loginSchema, noEchoHook)
|
|||||||
// Increment the counter even on 429 so continued brute-force accumulates toward lockout.
|
// Increment the counter even on 429 so continued brute-force accumulates toward lockout.
|
||||||
if (live && live.count >= RATE_WINDOW_FAILURES && now < live.lockedUntil) {
|
if (live && live.count >= RATE_WINDOW_FAILURES && now < live.lockedUntil) {
|
||||||
live.count += 1;
|
live.count += 1;
|
||||||
live.lockedUntil = now + RATE_WINDOW_SECS * 1000;
|
// WR-06: do NOT extend lockedUntil here. This request was itself REJECTED by the window;
|
||||||
|
// re-arming the cooldown on every blocked attempt let an attacker who keeps hammering the
|
||||||
|
// endpoint slide the window forward forever, so a legitimate user behind the same identity
|
||||||
|
// could never get back in even after pausing. The window stays anchored to when it was
|
||||||
|
// first armed (in the failure path below); it expires on schedule regardless of rejected
|
||||||
|
// traffic. The lockout (423) still triggers once the failure count crosses the threshold.
|
||||||
live.lockedOut = live.count >= LOCKOUT_FAILURES;
|
live.lockedOut = live.count >= LOCKOUT_FAILURES;
|
||||||
if (live.lockedOut) live.lockedAt = now;
|
if (live.lockedOut && live.lockedAt === 0) live.lockedAt = now;
|
||||||
loginAttempts.set(key, live);
|
loginAttempts.set(key, live);
|
||||||
if (live.lockedOut) {
|
if (live.lockedOut) {
|
||||||
return c.json({ error: 'Account locked' }, 423);
|
return c.json({ error: 'Account locked' }, 423);
|
||||||
|
|||||||
Reference in New Issue
Block a user