| Titolo | https://github.com/chenyme/ grok2api v3.1.6 Uncontrolled Resource Consumption |
|---|
| Descrizione | Voice/STT WebSocket sessions retain capacity past the configured request timeout
Affected versions: confirmed present in the latest tagged release, v3.1.6, and on the default branch `main` at commit `7c889a960e2638341b4dae9a5c81af0e0f38c87f`.
## Summary
Established realtime and STT WebSocket connections do not observe request-context cancellation. `server.requestTimeout` is implemented by attaching a `context.WithTimeout` deadline to the request, but once a voice/STT WebSocket session is established, nothing in the proxy path ever checks whether that context has expired. A client holding a quiet, already-admitted session keeps its account lease, concurrency slot, and upstream connection open indefinitely, well past the configured deadline, bounded only by whatever the upstream connection or the client eventually does on its own.
## Details
`backend/internal/transport/http/middleware/request.go` installs the deadline but never forcibly terminates the handler:
```go
ctx, cancel := context.WithTimeout(c.Request.Context(), duration)
defer cancel()
c.Request = c.Request.WithContext(ctx)
c.Next()
```
`backend/internal/transport/http/inference/voice_ws_handler.go`'s `proxyVoiceWebSocket` starts two blocking proxy pumps and waits only for one of them to return:
```go
errCh := make(chan pumpResult, 2)
go func() { errCh <- pumpResult{result: proxyVoiceWSPump(...)} }()
go func() { errCh <- pumpResult{upstreamSide: true, result: proxyVoiceWSPump(...)} }()
first := <-errCh
```
There is no `select` on `c.Request.Context().Done()` anywhere in this path. The account lease is released only inside `session.Finalize`, called from `closeAll`, which in turn only ran when one of the two pumps hit a transport error. A session with no activity on either side simply never hits that path until something else (an upstream idle timeout, a client closing) eventually does.
## POC
(available upon request)
## Impact
A client with a valid API key for realtime voice or streaming STT can open a session and leave both sides quiet, retaining the admitted account lease and concurrency slot beyond the server's configured `requestTimeout`. This does not bypass authentication or exceed a client's admitted concurrency limits; it extends how long already-admitted sessions can hold shared resources, which can reduce capacity available to other clients if repeated across multiple sessions.
Suggested fix: watch `c.Request.Context().Done()` alongside the two proxy pumps and close both sockets (triggering the existing finalize/cleanup path) the moment the context is canceled, so the configured request timeout bounds an established session's lifetime, not just its setup phase. A fix implementing exactly this, with a regression test, is included in the linked pull request.
|
|---|
| Fonte | ⚠️ https://github.com/chenyme/grok2api/issues/1071 |
|---|
| Utente | carfeii (UID 97470) |
|---|
| Sottomissione | 14/10/2026 14:58 (23 giorni fa) |
|---|
| Moderazione | 06/11/2026 13:58 (23 days later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 431905 [chenyme grok2api fino a 3.1.6 WebSocket Proxy voice_ws_handler.go proxyVoiceWebSocket negazione del servizio] |
|---|
| Punti | 20 |
|---|