Description
Version
>=18.16.0
Platform
All
Subsystem
_http_common.js
What steps will reproduce the bug?
NodeJS is actively preventing characters in the extended ascii table from passing in as a string.
Evidence: When using writeHead()
with headers parameter. It throws an ERR_INVALID_CHAR
error.
However, when we use setHeader()
. It does not validate the characters passed in.
const { createServer } = require("http");
const requestListener = function (req, res) {
res.setHeader("Content-Length", "310");
res.setHeader("Content-Disposition", `attachment; filename="ÇÕÑêÿ Island"`);
// res.writeHead(200, [
// "Content-Length", "310",
// "Content-Disposition", `attachment; filename="ÇÕÑêÿ Island"`
// ]);
res.end();
};
const server = createServer(requestListener);
server.listen(8080);
How often does it reproduce? Is there a required condition?
It always occurs when using the setHeader()
function with latin1
(extended ASCII table)
What is the expected behavior? Why is that the expected behavior?
The expected behaviour would be setHeader()
function rejects non-ascii string.
Source: According to this PR http: unify header treatment by marco-ippolito · Pull Request #46528 · nodejs/node. Header value validation always rejects non-ascii characters. To support latin1
in the Content-Disposition
HTTP header, the server has to parse the string as a binary string (within the ascii range). Just like what's written in the test https://github.com/nodejs/node/blob/main/test/parallel/test-http-server-non-utf8-header.js
What do you see instead?
setHeader()
does not reject non-ascii string. Content-Disposition header got parsed incorrectly.
For example: An input of attachment; filename="ÇÕÑêÿ Island" becomes attachment; filename="ýýýýý Island"
Additional information
Through debugging, I found it really strange that checkInvalidHeaderChar()
is behaving weirdly with the header value passed in from the writeHead()
and setHeader()
. writeHead()
passes a string buffer which gets regex'ed/rejected correctly but setHeader()
passes a plain string and it does not trigger the regex.