On Mon, Jan 19, 2026 at 08:46:43AM +0100, Willy Tarreau wrote:
> Hi Ben, Rajat,
> 
> On Sun, Jan 18, 2026 at 08:49:04PM +0000, Ben Kallus wrote:
> > Haven't reviewed, this, but wanted to chime in with a correction:
> > 
> > > A quoted-string continues until the closing DQUOTE, even if it contains
> > `\r\n` sequences.
> > 
> > This isn't true. An RFC-compliant parser should reject \r\n within a
> > chunk-ext and respond 400. Go look at the definitions of qdtext and
> > quoted-pair; neither one allows CR or LF.
> > 
> > If nginx indeed behaves the way you claim, this is also a bug in nginx.
> 
> So I've rechecked the various RFCs and I agree with you:
> 
> RFC9112/7.1.1:
>   chunk-ext      = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val 
> ] )
>   chunk-ext-name = token
>   chunk-ext-val  = token / quoted-string
> 
> RFC9110:
>   quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
>   qdtext         = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text
>   quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )
>   obs-text       = %x80-FF
>   VCHAR          = any visible US-ASCII character  (i.e. %x21-7E)
> 
>   "A recipient MUST ignore unrecognized chunk extensions."
> 
> So here since we use no such extension, we just ignore them all, which
> also means that we don't implement code to validate that those we're
> supposed to ignore have correctly paired quotes, since CR/LF are forbidden
> within these quotes anyway.
> 
> The chunk size parser tries to follow these rules as closely as possible
> (while correctly ignoring the extensions):
> 
>    h1_parse_chunk_size():
> 
>         /* The chunk size is in the following form, though we are only
>          * interested in the size and CRLF :
>          *    1*HEXDIGIT *WSP *[ ';' extensions ] CRLF
>          */
>         (...)
>         if (likely(*ptr == ';')) {
>               /* chunk extension, ends at next CRLF */
>               (...)
> 
> Now we can see what it would cost to check for unmatched quotes in the
> extension anyway. I gave it a try with the attached patch. Could you
> please check if it suffices to protect the server ? I think it could
> reasonably be backported if it helps. However I'm not seeing that as
> a bug given that we follow the spec.
> 
> Rajat, if you want to share your PoC (even though I understand how it
> works), you can send it to security at haproxy.org.

By the way there are two things I don't understand:

  - I tried hard to make nginx misbehave on chunk extensions and failed.
    It seems to proceed exactly like us so I don't see how both together
    could fail in this case ;

  - in your screenshot, it's visible that there are two HTTP replies
    for NGINX and two as well for haproxy (based on the logs), so here
    there is no smuggling.

Am I missing anything ? What does your request look like ?

Thanks,
Willy


Reply via email to