fix(security): rate-limit login + 2FA challenge endpoints (LC-151) #184
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-151-login-rate-limit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Closes the unthrottled-login gap from the LC-148 audit (finding S5). Registration was per-IP rate-limited but
POST /login,POST /login/2fa, andPOST /login/recoverywere not, leaving online password + TOTP/recovery-code brute force unthrottled.Fix
RateLimitKind::Loginbucket and a sharedenforce_login_rate_limithelper, called at the top of all three handlers (before any password/code verify), so attempts count regardless of success.rate_limit_loginssetting (0= disabled), surfaced on the admin anti-spam page next to the existing caps.client_ip_for_rate_limitreturnsNoneand no-ops otherwise) - the admin field help text says so. Consistent with the existing register/message limiters.Test
routes_anti_spam:login_rate_limit_returns_429_after_cap(Nth+1 wrong-password attempt from one IP -> 429, different IP unaffected) andlogin_and_2fa_challenge_share_one_per_ip_budget(a/login/2faattempt is throttled on the budget burned via/login, and the rate-limit check precedes the pending-cookie check so it 429s even with no valid challenge).just check/just test/just test-saasgreen (theroutes_uploadsupload-pipeline flake under concurrent-binary load is pre-existing and passes in isolation - this PR touches no upload code).Part of the LC-159 post-audit story.
🤖 Generated with Claude Code