mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 22:03:13 -06:00
The only throttle on POST /api/auth/login was the per-IP limiter in server.js. That bounds one noisy source and nothing else: it does not bound a distributed attempt, and it is only as accurate as a deployment's proxy configuration. Nothing counted failures against the account actually being attacked, and nothing cleared such a count on success because no such count existed. lib/login-lockout.js mirrors lib/totp-lockout.js and lib/pair-lockout.js so there is one lockout idiom here rather than three. 10 failed passwords lock an account for 15 minutes. Keyed on user.id, never on the submitted email: the email is attacker-supplied and unbounded, so keying on it would let anyone grow the Map without limit — the same class of bug fixed elsewhere in this campaign. A user id only exists for a real account, so the key space is bounded by the user table and needs no eviction sweep, exactly like totp-lockout. A locked account returns the SAME 401 and body as a wrong password. A distinct 429 would tell an attacker "this account exists and is under attack", turning login into an account-existence oracle; the test asserts the locked response is byte-identical to both the wrong-password and unknown-account responses. The trade is that a locked-out legitimate user sees the generic message, so the trip is recorded in activity_log (auth:login_locked) for the operator instead. The counter is cleared as soon as the password verifies — before the TOTP and email-verification branches, which return early and never reach issueSession, so a reset placed there would never fire for those accounts. SSO paths do not share this code and are unaffected. Frontend needs no change: login.js renders any non-ok body's `error` string verbatim, and the body is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| activity.js | ||
| admin.js | ||
| agency.js | ||
| ai.js | ||
| assignments.js | ||
| auth.js | ||
| billing.js | ||
| contact.js | ||
| content.js | ||
| device-groups.js | ||
| devices.js | ||
| folders.js | ||
| kiosk.js | ||
| layouts.js | ||
| media.js | ||
| pip.js | ||
| player-debug.js | ||
| playlists.js | ||
| provisioning.js | ||
| reports.js | ||
| schedules.js | ||
| status.js | ||
| stripe.js | ||
| subscription.js | ||
| teams.js | ||
| tokens.js | ||
| video-walls.js | ||
| white-label.js | ||
| widgets.js | ||
| workspaces.js | ||