Skip to content

Bug report: Dechunk HTTP Response leaks terminating chunk and trailers into output #2247

@williballenthin

Description

@williballenthin

Describe the bug
The Dechunk HTTP response operation does not handle the terminating zero-length chunk defined by RFC 7230, causing trailing metadata to leak into the decoded output.

src/core/operations/DechunkHTTPResponse.mjs, run() method, lines 47-55

while (!isNaN(chunkSize)) {
    chunks.push(input.slice(chunkSizeEnd, chunkSize + chunkSizeEnd));
    input = input.slice(chunkSizeEnd + chunkSize + lineEndingsLength);
    chunkSizeEnd = input.indexOf(lineEndings) + lineEndingsLength;
    chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16);
}
return chunks.join("") + input;

A chunked HTTP response is terminated by 0\r\n\r\n, optionally with trailer headers between the two CRLFs. When the loop encounters chunkSize === 0, it does not break — 0 is not NaN, so the loop continues. It pushes an empty string, slices past the zero chunk, and then tries to parse whatever remains (the trailing CRLF or trailer headers) as the next chunk size. That fails with NaN, exiting the loop, but the remaining text is returned verbatim via chunks.join("") + input.

To Reproduce
https://gchq.github.io/CyberChef/#recipe=Dechunk_HTTP_response()&input=NwpNb3ppbGxhCjkKRGV2ZWxvcGVyCjcKTmV0d29yawowCkV4cGlyZXM6IFdlZCwgMjEgT2N0IDIwMTUgMDc6Mjg6MDAgR01UCg

Image Image

Additional context
Suggested fix:

while (!isNaN(chunkSize)) {
    chunks.push(input.slice(chunkSizeEnd, chunkSize + chunkSizeEnd));
    input = input.slice(chunkSizeEnd + chunkSize + lineEndingsLength);
    chunkSizeEnd = input.indexOf(lineEndings) + lineEndingsLength;
    chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16);
    if (chunkSize === 0) {
        input = input.slice(chunkSizeEnd);
        if (input.startsWith(lineEndings)) {
            input = input.slice(lineEndingsLength);
        }
        break;
    }
}
return chunks.join("") + input;

This explicitly detects the terminating chunk, consumes it and its trailing CRLF, and breaks out of the loop before the trailer data can be appended to the output.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions