Remediate PEN-01 through PEN-07 (pentest round 4)
- PEN-01: fix extractBearerFromRequest to validate Bearer prefix using strings.SplitN + EqualFold; add TestExtractBearerFromRequest - PEN-02: security headers confirmed present after redeploy (live probe 2026-03-15) - PEN-03: accepted — Swagger UI self-hosting disproportionate to risk - PEN-04: accepted — OpenAPI spec intentionally public - PEN-05: accepted — gRPC port 9443 intentionally public - PEN-06: remove RecordLoginFailure from REST TOTP-missing branch to match gRPC handler (DEF-08); add TestTOTPMissingDoesNotIncrementLockout - PEN-07: accepted — per-account hard lockout covers the same threat - Update AUDIT.md: all 7 PEN findings resolved (4 fixed, 3 accepted) Security: PEN-01 removed a defence-in-depth gap where any 8+ char Authorization value was accepted as a Bearer token. PEN-06 closed an account-lockout-via-omission attack vector on TOTP-enrolled accounts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -271,8 +271,13 @@ func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
// TOTP check (if enrolled).
|
||||
if acct.TOTPRequired {
|
||||
if req.TOTPCode == "" {
|
||||
// Security (DEF-08 / PEN-06): do NOT increment the lockout counter
|
||||
// for a missing TOTP code. A missing code means the client needs to
|
||||
// re-prompt the user — it is not a credential failure. Incrementing
|
||||
// here would let an attacker trigger account lockout by omitting the
|
||||
// code after a correct password guess, and would penalise well-behaved
|
||||
// clients that call Login in two steps (password first, TOTP second).
|
||||
s.writeAudit(r, model.EventLoginFail, &acct.ID, nil, `{"reason":"totp_missing"}`)
|
||||
_ = s.db.RecordLoginFailure(acct.ID)
|
||||
middleware.WriteError(w, http.StatusUnauthorized, "TOTP code required", "totp_required")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user