-
Notifications
You must be signed in to change notification settings - Fork 1.5k
http_parser: revert memchr()
optimization
#469
Conversation
An optimization was introduced in c6097e1 and 0097de5. The crux of optimization was to skip all characters in header value until either of CR or LF. Unfortunately, this optimization comes at cost of inconsistency in header value validation, which might lead to security issue due to violated expectations in the user code. Partially revert the optimization, and add additional check to make general header value parsing consistent. Fix: nodejs#468
cc @nodejs/http . I do not believe that there is any security risk for Node.js applications. However, since this is causing a public security issue for envoyproxy, I'd suggest we act promptly on this. Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not an expert here, but this looks like it works to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fix! A few minor comments.
@@ -4316,6 +4316,9 @@ main (void) | |||
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION); | |||
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION); | |||
|
|||
test_simple("GET / HTTP/1.0\r\nHello: w\1rld\r\n\r\n", HPE_INVALID_HEADER_TOKEN); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you could also test with explicit \0
I think it would be great, since NULs are particularly tricky when it comes to C strings as a special case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that there's point to checking \0
too. However, this works without further changes to the code, because strlen()
still returns correct value. Perhaps, we should address it in a separate follow-up change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine too.
http_parser.c
Outdated
for (; p != data + len; p++) { | ||
ch = *p; | ||
if (ch == CR || ch == LF) { | ||
--p; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you remove this, can you then skip the if
below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a revert of the change. I'd rather keep it closer to the original code, unless there are other reasons for improving it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick fix. Can you advise on the best way to report security vulnerabilities related to http-parser in the future?
An optimization was introduced in c6097e1 and 0097de5. The crux of optimization was to skip all characters in header value until either of CR or LF. Unfortunately, this optimization comes at cost of inconsistency in header value validation, which might lead to security issue due to violated expectations in the user code. Partially revert the optimization, and add additional check to make general header value parsing consistent. Fix: #468 PR-URL: #469 Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Harvey Tuch <htuch@google.com>
Landed in 2a0d106. Thank you everyone! @htuch I'd use Node.js security channels for this. https://nodejs.org/en/security/ Thanks again for reporting it! |
An optimization was introduced in c6097e1 and 0097de5. The crux of optimization was to skip all characters in header value until either of CR or LF. Unfortunately, this optimization comes at cost of inconsistency in header value validation, which might lead to security issue due to violated expectations in the user code. Partially revert the optimization, and add additional check to make general header value parsing consistent. Fix: nodejs#468 PR-URL: nodejs#469 Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Harvey Tuch <htuch@google.com>
@indutny @nodejs/http Can anyone confirm that this does not affect Node.js? #469 (comment) --- why would it not affect Node.js? Because it looks like it could affect Node.js, in which case we'd need a CVE for it and to backport the fix to LTS branches. |
I believe it would not affect Node.js due to the way the header values are converted to V8 strings in Node. We use |
An optimization was introduced in c6097e1 and 0097de5. The crux of
optimization was to skip all characters in header value until either
of CR or LF. Unfortunately, this optimization comes at cost of
inconsistency in header value validation, which might lead to security
issue due to violated expectations in the user code.
Partially revert the optimization, and add additional check to make
general header value parsing consistent.
Fix: #468