reCAPTCHA verification uses an http.Client with no timeout on the synchronous login path (login-thread stall risk)
low Possibly Valid medium confidence
Status
Possibly Valid
The missing-timeout code defect on a request path is confirmed, but the availability impact depends on non-attacker-controlled upstream slowness, so possibly_valid with that precondition named.
Repository / Component
Plain-English Description
When reCAPTCHA is enabled, each login waits for a reply from the reCAPTCHA service using a connection that has no time limit. If that service is slow or unreachable, login requests can hang indefinitely and stack up.
Description of the Underlying Issue
ReCaptcha.Ok (auth/json.go:91-122) creates an outbound HTTP client with client := &http.Client{} (auth/json.go:96) that sets no Timeout, and performs a synchronous client.Post to the reCAPTCHA verification API (auth/json.go:98-102) with no context deadline, directly on the login request's goroutine. JSONAuth.Auth invokes a.ReCaptcha.Ok during /api/login whenever the reCAPTCHA Secret is configured (auth/json.go:46-47). Because neither a client Timeout nor a request context deadline is set, a slow or unresponsive reCAPTCHA endpoint causes each affected login goroutine to block for as long as the connection stays open, allowing concurrent logins to pile up.
Potential Attack
This is chiefly an availability/robustness defect whose trigger is not attacker-controlled: if the configured reCAPTCHA host (normally Google's servers) becomes slow, unreachable, or is subject to a network partition or DNS problem, every login attempt blocks on the timeout-less POST. Ordinary or attacker-amplified login volume during such an upstream stall then accumulates blocked goroutines. An attacker cannot force the upstream to hang, but can amplify the impact by driving login traffic while the condition holds.
Outcomes of Potential Attack
Degraded or unavailable authentication: login requests hang and server goroutines/connections accumulate while the reCAPTCHA endpoint is unresponsive, potentially exhausting resources and preventing legitimate logins until the upstream recovers or the process is restarted. No data disclosure or privilege gain.
Affected Scope
ReCaptcha.Ok (auth/json.go:91-122) on the /api/login path when reCAPTCHA Secret is set
Suggested Fix (plain english)
Give the reCAPTCHA verification request a strict time limit so a slow service fails the check quickly instead of hanging the login.
Suggested Fix (detailed)
Set http.Client.Timeout (or attach a context.WithTimeout deadline to the request) on the reCAPTCHA verification in ReCaptcha.Ok (auth/json.go:96-102), and treat a timeout as a verification failure rather than an indefinite block. Verify by pointing the reCAPTCHA host at an unresponsive endpoint and confirming that login attempts fail fast within the configured deadline instead of accumulating blocked goroutines. Set http.Client.Timeout or attach a context deadline to the reCAPTCHA verification request.
Validation
The missing-timeout code defect on a request path is confirmed, but the availability impact depends on non-attacker-controlled upstream slowness, so possibly_valid with that precondition named.
Full Evidence
auth/json.go:96 client := &http.Client{} with no Timeoutauth/json.go:98-102 synchronous client.Post(r.Host+reCaptchaAPI, ...) on the login request goroutine
auth/json.go:46-47 JSONAuth.Auth invokes a.ReCaptcha.Ok on /api/login when Secret != ''
Proven fact: The outbound reCAPTCHA verification uses an http.Client with no timeout and no context deadline, on the synchronous login path
Unvalidated fact: A stall requires the configured reCAPTCHA host to be slow/unreachable, which is NOT attacker-controlled (normally Google's servers)
Unvalidated fact: Only reachable when reCAPTCHA is enabled (Secret configured)
auth/json.go:96 — client := &http.Client{} with no Timeoutauth/json.go:98-102 — synchronous client.Post(reCaptchaAPI, ...) on the login request goroutine, with no context deadline
auth/json.go:46-47 — JSONAuth.Auth invokes a.ReCaptcha.Ok on /api/login when Secret != ''
Proven fact: The outbound reCAPTCHA verification uses an http.Client with no timeout and no context deadline, on the synchronous login path.
Proven fact: The verification runs inline on the login goroutine whenever reCAPTCHA Secret is set, so a stalled request stalls that login.
Unvalidated fact: A stall requires the configured reCAPTCHA host to be slow/unreachable, which is NOT attacker-controlled (normally Google's servers).
Unvalidated fact: Only reachable when reCAPTCHA is enabled (Secret configured).
auth/json.go:96 client := &http.Client{} (no Timeout)auth/json.go:33-56 Auth invokes ReCaptcha.Ok on the /api/login path when Secret is set