HTTP Request Smuggling (desync shapes)
First-party proxy, forwarding, or hand-rolled HTTP parsing code lets a front-end and a back-end disagree about where one request ends and the next begins. An attacker uses that disagreement to prepend bytes to somebody else's request, which is how a desync turns into credential theft or cache poisoning.
What Vulkro detects
Two deterministic shape rules, both Medium, over the project's own source. Neither is a taint proof and neither is a live desync test.
SMUGGLE-001 (Medium) fires when a reverse-proxy or forwarding path copies a client-supplied Transfer-Encoding header onto the outbound upstream request, for example inside a httputil.ReverseProxy Director or a manual passthrough loop. The message calls out the higher-risk case where both Transfer-Encoding and Content-Length are forwarded. A proxy that strips hop-by-hop headers (Header.Del("Transfer-Encoding")) never matches, and a proxy context is required so an ordinary Content-Length write is not flagged.
SMUGGLE-002 (Medium, heuristic) fires on a hand-rolled HTTP parser that reads Content-Length off a raw connection (bufio.NewReader, ReadString, a manual header loop) and parses it to an integer with no visible guard rejecting a duplicate or conflicting Content-Length / Transfer-Encoding. A parser that already mentions a duplicate or ambiguity guard is skipped.
Scope: this detector only reasons about first-party source shapes. The library-version half of the risk (a vulnerable stdlib or proxy dependency) belongs to the dependency scan, not here.
Remediation. Strip hop-by-hop headers before forwarding, and let one component own request framing: never re-send a client Transfer-Encoding. In a hand-rolled parser, reject a request carrying more than one Content-Length, or both Content-Length and Transfer-Encoding, with a 400 rather than picking a winner.
Non-compliant code (examples)
Go - proxy forwards the client's Transfer-Encoding
proxy.Director = func(req *http.Request) {
req.Header.Set("Transfer-Encoding", clientReq.Header.Get("Transfer-Encoding"))
req.Header.Set("Content-Length", clientReq.Header.Get("Content-Length"))
}
Compliant code (examples)
Go - hop-by-hop headers dropped, framing left to the client library
proxy.Director = func(req *http.Request) {
req.Header.Del("Transfer-Encoding")
req.Header.Del("Connection")
// net/http sets the framing headers itself from req.Body / ContentLength
}
See also
- Confidence model - what
High,Medium, andLowmean for findings in this category. - Safety - what Vulkro does and does not access on your machine.
References
This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.