An answer from the app without a Content-Type can reach the client with one Go guessed #127

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

internal/proxy/request.go, forward: httputil.ReverseProxy copies the app's headers to the client's response and writes the body through Go's HTTP server. When the app's answer has neither Content-Type nor Content-Encoding, Go's server guesses a type from the first bytes of the body (DetectContentType) and adds it, whenever the first part of the body is written before the headers have gone out on their own. With FlushInterval at -1 the two race, so some answers get the header and others do not.

Repro, at the defaults: an app that answers a short HTML page with no Content-Type (in Go, w.Header()["Content-Type"] = nil). Asked directly, it sends none. Asked 50 times through smallwebwaf, in three runs 6, 9 and 16 of the 50 answers carried Content-Type: text/html; charset=utf-8.

README, "What it does so far": "Passes each request to the app and the app's answer back unchanged: method, path, query, headers, body and status." A guessed type can change how a browser treats the answer. The request log's response_content_type stays empty for such an answer, while the client got a type.

Untested: in modifyResponse, setting the client's Content-Type to nil when the app sent none should keep Go from adding one.

Severity: minor.

Model: opus-5-5

`internal/proxy/request.go`, `forward`: `httputil.ReverseProxy` copies the app's headers to the client's response and writes the body through Go's HTTP server. When the app's answer has neither `Content-Type` nor `Content-Encoding`, Go's server guesses a type from the first bytes of the body (`DetectContentType`) and adds it, whenever the first part of the body is written before the headers have gone out on their own. With `FlushInterval` at -1 the two race, so some answers get the header and others do not. Repro, at the defaults: an app that answers a short HTML page with no `Content-Type` (in Go, `w.Header()["Content-Type"] = nil`). Asked directly, it sends none. Asked 50 times through `smallwebwaf`, in three runs 6, 9 and 16 of the 50 answers carried `Content-Type: text/html; charset=utf-8`. README, "What it does so far": "Passes each request to the app and the app's answer back unchanged: method, path, query, headers, body and status." A guessed type can change how a browser treats the answer. The request log's `response_content_type` stays empty for such an answer, while the client got a type. Untested: in `modifyResponse`, setting the client's `Content-Type` to nil when the app sent none should keep Go from adding one. 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#127