Skip to content

fix(security): rate limit backup code login and enforce CSRF on 2FA challenges - #126

Open
palmoni5 wants to merge 1 commit into
NodeBB:masterfrom
palmoni5:fix/backup-code-hardening
Open

palmoni5 wants to merge 1 commit into
NodeBB:masterfrom
palmoni5:fix/backup-code-hardening

Conversation

@palmoni5

@palmoni5 palmoni5 commented Sep 5, 2026 •

Copy link
Copy Markdown

Summary

Hardens the backup-code and TOTP challenge routes.

1. No rate limiting on POST /login/2fa/backup

processTotpLogin has a per-uid lock (locks:totp:<uid>), a 2s delay on failure, and a 10s penalty when spammed. processBackup had none of these, so backup codes could be brute-forced online with no throttling. This PR mirrors the TOTP behaviour using locks:backup:<uid>. The lock is cleared on success, on failure (after the 2s delay) and on exception, matching the TOTP path.

2. No CSRF protection on the two challenge POSTs

POST /login/2fa/totp and POST /login/2fa/backup ran without applyCSRF, while the PUT /login/2fa/backup route already had it. The templates rendered a hidden field named csrf, but core's CSRF middleware only reads csrf_token / _csrf, so the token was never checked. Both routes now use hostMiddleware.applyCSRF and the templates send csrf_token.

3. Backup code entropy

utils.generateUUID().replace('-', '') removes only the first dash, so codes were 10 hex characters (~40 bits). They are now generated with crypto.randomBytes(6) (12 hex chars). Existing codes keep working unchanged.

🤖 Generated with Claude Code

@julianlam

Copy link
Copy Markdown
Member

Not overly concerned about the backup code hashing — stated rationale is weak.

Exploitation of plaintext stored backup codes requires database access or exfiltration vector. If that is the case it's game over already.

@palmoni5 palmoni5 closed this Oct 25, 2026
@julianlam

Copy link
Copy Markdown
Member

Well, the rest of it was good 🤔

@palmoni5 palmoni5 reopened this Oct 25, 2026
@palmoni5
palmoni5 force-pushed the fix/backup-code-hardening branch from 520a8bc to 18aefa4 Compare October 25, 2026 17:18
@palmoni5 palmoni5 changed the title fix(security): harden backup code login path (hashing, rate limit, CSRF) fix(security): rate limit backup code login and enforce CSRF on 2FA challenges Oct 25, 2026
@palmoni5

Copy link
Copy Markdown
Author

Fair point on the hashing, I've dropped it. The branch is rebased onto current master and now only contains the rate limit on the backup code route, CSRF on both challenge POSTs, and the backup code generation fix (existing codes still work, nothing changes in storage).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants