An upgrade the app accepts under another protocol name is answered 200 with an empty body #131

Open
opened 2026-10-14 18:13:37 +02:00 by clawbot · 0 comments
Collaborator

internal/proxy/request.go, modifyResponse and answer. modifyResponse notes status 101 in rq.out.status as soon as the app answers 101. httputil.ReverseProxy then refuses the switch when the app's Upgrade differs from the client's, and calls answerError, whose answer(502) returns at once because rq.out.status is no longer 0, although nothing was sent. The handler returns having written nothing, and Go's server sends 200 OK with an empty body.

Repro, at the defaults: a client sends GET /ws HTTP/1.1 with Connection: Upgrade and Upgrade: websocket, foo, and the app answers 101 Switching Protocols with Upgrade: websocket, as an app that accepts any Upgrade list holding websocket would. The client gets 200; the log line has status 101 and action upstream_error.

README, request log: "status is what the client was sent". The client is told the exchange succeeded when it failed; answerError meant to send 502.

From reading the code, not tested: nothing closes the app's switched connection on this path.

Severity: minor.

Model: opus-5-5

`internal/proxy/request.go`, `modifyResponse` and `answer`. `modifyResponse` notes status 101 in `rq.out.status` as soon as the app answers 101. `httputil.ReverseProxy` then refuses the switch when the app's `Upgrade` differs from the client's, and calls `answerError`, whose `answer(502)` returns at once because `rq.out.status` is no longer 0, although nothing was sent. The handler returns having written nothing, and Go's server sends `200 OK` with an empty body. Repro, at the defaults: a client sends `GET /ws HTTP/1.1` with `Connection: Upgrade` and `Upgrade: websocket, foo`, and the app answers `101 Switching Protocols` with `Upgrade: websocket`, as an app that accepts any `Upgrade` list holding `websocket` would. The client gets `200`; the log line has status 101 and action `upstream_error`. README, request log: "`status` is what the client was sent". The client is told the exchange succeeded when it failed; `answerError` meant to send 502. From reading the code, not tested: nothing closes the app's switched connection on this path. Severity: minor. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/smallwebwaf#131