From: Turhan ACAR Date: Thu, 24 Sep 2026 14:38:35 +0000 (+0100) Subject: BUG/MINOR: h2: reject :protocol pseudo-header in H2 responses X-Git-Tag: v3.5-dev8~115 X-Git-Url: https://git.kaiwu.me/$%7BISSUES%7D/static/gitweb.js?a=commitdiff_plain;h=4ddf219bb399334e00a0b9af2b155884befd4b04;p=haproxy.git BUG/MINOR: h2: reject :protocol pseudo-header in H2 responses RFC 7540#8.1.2.1 mandates that pseudo-headers defined for requests must not appear in responses. When converting an HTTP/2 response to HTX, h2.c already rejects a response carrying :authority, :method, :path or :scheme, but the mask used for that check omits H2_PHDR_FND_PROT. As a result a backend HTTP/2 response that contains the request-only ":protocol" pseudo-header (defined by RFC 8441 for Extended CONNECT) is accepted and forwarded to the client instead of being rejected. Add H2_PHDR_FND_PROT to the response-side rejection mask so that ":protocol" is handled like the other request pseudo-headers and such a response yields a 502 instead of being forwarded. There is no known security impact: the offending pseudo-header does not appear in the emitted HTTP/1 response (which is byte-identical to that of a valid one); the only effect is that a malformed response is tolerated instead of being rejected. This should be backported as far back as 2.4, where the ":protocol" pseudo-header (H2_PHDR_FND_PROT) was introduced; the maintainer may narrow the range to the currently maintained branches. Signed-off-by: Turhan ACAR --- diff --git a/src/h2.c b/src/h2.c index d2f691b6e..1d21f5e95 100644 --- a/src/h2.c +++ b/src/h2.c @@ -750,8 +750,8 @@ int h2_make_htx_response(struct http_hdr *list, struct htx *htx, unsigned int *m goto fail; } - /* RFC7540#8.1.2.1 mandates to reject request pseudo-headers */ - if (fields & (H2_PHDR_FND_AUTH|H2_PHDR_FND_METH|H2_PHDR_FND_PATH|H2_PHDR_FND_SCHM)) + /* Reject request pseudo-headers, including RFC8441's :protocol. */ + if (fields & (H2_PHDR_FND_AUTH|H2_PHDR_FND_METH|H2_PHDR_FND_PATH|H2_PHDR_FND_SCHM|H2_PHDR_FND_PROT)) goto fail; /* Let's dump the response now if not yet emitted. */