Harden HTTP proxy header handling#440
Conversation
Block hop-by-hop response headers from being forwarded through the HTTP proxy and handle invalid x-ms-client-principal payloads without failing the invocation. Co-authored-by: Dobby <dobby@microsoft.com>
| proxyRes.setHeader(key, val); | ||
| if (isAllowedProxyResponseHeader(key)) { | ||
| proxyRes.setHeader(key, val); | ||
| } |
There was a problem hiding this comment.
Content-Length is an end-to-end header, and customers may set it intentionally for HEAD/304/206 responses, downloads, or other scenarios where clients rely on it. Dropping it could change behavior for existing apps.
Can you check RFC Compliant docs if we can preseves 'content-length'.
There was a problem hiding this comment.
Good point. \Content-Length\ is an end-to-end header, and dropping it may have compatibility impact for HEAD/304/206/download scenarios. I am leaving this thread open for discussion rather than changing it blindly. My original concern was mismatched framing when proxying streamed bodies; we should decide whether preserving it is preferred or whether only conflicting cases should be filtered.
There was a problem hiding this comment.
So what's your recommendation?
There was a problem hiding this comment.
My recommendation is to preserve Content-Length and remove it from the blocked header list.
Content-Length is end-to-end response metadata, not a hop-by-hop header, and removing other hop-by-hop headers does not change the response body bytes. Dropping it could break existing apps that intentionally set it, especially for HEAD/304/206/download scenarios.
The original concern was about forwarding connection/framing controls through this proxy. This code copies user response headers to Node.js ServerResponse, then writes the response body through proxyRes.write(...). If we forward headers like Connection, TE, Trailer, Transfer-Encoding, or Upgrade, those headers can describe connection-specific behavior or wire framing that should be owned by the proxy/Node response layer instead.
To address that without treating Content-Length as hop-by-hop, I updated the implementation to:
- allow
content-length; - keep blocking the standard hop-by-hop headers;
- also strip any header names listed by the
Connectionheader, becauseConnection: x-private-hopmarksx-private-hopas connection-specific and a proxy should not forward it.
I am not validating Content-Length against the streamed body here, because that would require buffering/counting the stream and would weaken the streaming path. If a user sets an incorrect Content-Length, that is a response correctness issue separate from this hop-by-hop proxy hardening.
Allow Content-Length through the HTTP proxy while continuing to block hop-by-hop headers. Also strip response headers named by the Connection header so connection-specific fields do not cross the proxy boundary. Co-authored-by: Dobby <dobby@microsoft.com>
Summary
x-ms-client-principalpayloads without failing the invocationNotes
F4 (
ensureErrorTypeobject serialization) is intentionally not changed in this PR. That area needs a separate design discussion because the safer fix likely requires sanitizer behavior aligned with azure-functions-host and azure-functions-nodejs-worker, not just using an object'smessageproperty.Validation
npm test(375 passed)npm run lint