Hi!

On Thu, Sep 24, 2026 at 03:38:35PM +0100, Turhan ACAR wrote:
> 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.

Oh, that's very interesting. I was wondering why it didn't happen in the
past, as I remembered that we only accept known pseudo-headers, and the
reason is this:

        else if (phdr != 0) {
                /* invalid pseudo header -- should never happen here */
                goto fail;
        }

Before :protocol was supported, phdr would have been -1 and would have
matched this one. This is no longer the case.

> 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 <[email protected]>
> ---
>  src/h2.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/src/h2.c b/src/h2.c
> index c66f79d..4821feb 100644
> --- a/src/h2.c
> +++ b/src/h2.c
> @@ -751,8 +751,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;

Yeah, your patch looks good, I'm applying it, thank you very much!
Willy


Reply via email to