-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Description
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.
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.