
Cloud Vulnerability DB
A community-led vulnerabilities database
When proxy-chain forwards a plain-HTTP request (every non-CONNECT proxy request goes through forward(), or forwardSocks() when the upstream is SOCKS), it fetches the origin response with Node's HTTP client explicitly set to lenient parsing (insecureHTTPParser: true), then rebuilds the downstream response: it strips the Transfer-Encoding header (hop-by-hop filter) while keeping the origin's Content-Length header verbatim, and pipes the full dechunked body into the client-facing response.
A malicious origin (any http:// URL the proxy client requests — the core use case of a crawling proxy) that sends a response carrying both Transfer-Encoding: chunked and a smaller Content-Length: N gets:
HPE_INVALID_TRANSFER_ENCODING — the insecureHTTPParser: true flag is what disarms that protection),Content-Length: N + the entire dechunked body (which exceeds N), on a keep-alive connection.
The bytes beyond position N are attacker-chosen and are parsed by the downstream client's HTTP stack as the response to its next request on that proxied connection. Because proxied HTTP/1.1 connections are per-proxy (requests use absolute-form and target arbitrary origins over one socket), the forged response can be served for a request to any origin, not just the attacker's — cross-origin response forgery / response splitting.
Verified locally with Node 22 (same llhttp family as the supported Node >= 20.11):rawHeaders keep both headers, body delivered = full dechunked length;forward() (writeHead with array headers incl. stale content-length, then pipeline(body, response)): all body bytes reach the wire despite the smaller declared Content-Length, connection stays keep-alive, and the smuggled HTTP/1.1 200 OK ... bytes answered a subsequent request sent on the same connection.proxy-chain (npm), Apache-2.0, by Apify — used by Apify Proxy, Crawlee, and anyone routing Puppeteer/Playwright through an authenticated proxy.Content-Length is no longer forwarded when the response carried a Transfer-Encoding header (RFC 9112 §6.3), so the client response is framed as chunked.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N (crawler/server-side deployment, the library's flagship use). A browser-user deployment scores the same 8.2 with UI:R/S:C.Attacker input: the HTTP response returned by an origin server / upstream proxy for a plain-HTTP request the proxy client made (attacker = controls any http:// origin the client is directed to; no auth against the attacker is needed — proxy auth, if any, is against the client).
src/server.ts:363 — onRequest() handles every non-CONNECT proxy request.src/server.ts:382-383 — no SOCKS upstream → await forward(request, response, handlerOpts) (SOCKS upstream → forwardSocks() at src/server.ts:376-379, same pattern, see step 8).src/forward.ts:59-66 — outbound request built; src/forward.ts:62 insecureHTTPParser: true → response parsing is lenient; TE+CL responses are accepted instead of rejected (strict Node rejects: HPE_INVALID_TRANSFER_ENCODING).src/forward.ts:116-126 — http.request(origin, options, requestCallback); origin response (clientResponse) carries rawHeaders = [..., 'Transfer-Encoding', 'chunked', 'Content-Length', N] and a dechunked stream longer than N.src/forward.ts:82 — requestCallback(clientResponse) invoked with the attacker-controlled response.src/forward.ts:96-100 — response.writeHead(statusCode, statusMessage, validHeadersOnly(clientResponse.rawHeaders)).src/utils/valid_headers_only.ts:24-26 (with src/utils/is_hop_by_hop_header.ts:8) — the hop-by-hop filter drops Transfer-Encoding and keeps Content-Length: N; no code reconciles N with the actual body length, and nothing forces Connection: close on framing mismatch.src/forward.ts:103-106 — await pipeline(clientResponse, response) streams the entire dechunked body under the stale Content-Length: N onto the downstream keep-alive socket. Bytes past N are the attacker's smuggled response. (Identical sink in src/forward_socks.ts:48 lenient flag, :69-73 writeHead, :76-79 pipeline.)
Sink: the proxy's client-facing socket (response / srcResponse) — the smuggled bytes are parsed by the downstream client as the response to its next pipelined request on that connection.Boundary crossed: origin-server → proxy-client response integrity. A malicious web server reached through the proxy can forge the HTTP response the proxy's client receives for a later request to any origin routed over the same proxied connection: content spoofing/injection for arbitrary origins, poisoning of client-side HTTP caches, cookie/session injection (Set-Cookie for other origins), XSS via crafted HTML, and deceptive data fed to crawlers. For Apify/Crawlee-style shared-proxy deployments this silently corrupts the integrity guarantee the proxy exists to provide.
Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."