GeezerVison is showing github.com — http: opt-in insecure HTTP header parsing · nodejs/node@3a7a3be
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/cli.md +11Lines changed: 11 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -431,6 +431,16 @@ added: v9.0.0 | 431 | 431 | Specify the `module` of a custom [experimental ECMAScript Module][] loader. | 432 | 432 | `module` may be either a path to a file, or an ECMAScript Module name. | 433 | 433 |
| | 434 | +### `--insecure-http-parser` | | 435 | +<!-- YAML | | 436 | +added: REPLACEME | | 437 | +--> | | 438 | + | | 439 | +Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow | | 440 | +interoperability with non-conformant HTTP implementations. It may also allow | | 441 | +request smuggling and other HTTP attacks that rely on invalid headers being | | 442 | +accepted. Avoid using this option. | | 443 | + | 434 | 444 | ### `--max-http-header-size=size` | 435 | 445 | <!-- YAML | 436 | 446 | added: v11.6.0 | @@ -1099,6 +1109,7 @@ Node.js options that are allowed are: | 1099 | 1109 | * `--http-server-default-timeout` | 1100 | 1110 | * `--icu-data-dir` | 1101 | 1111 | * `--input-type` | | 1112 | +* `--insecure-http-parser` | 1102 | 1113 | * `--inspect-brk` | 1103 | 1114 | * `--inspect-port`, `--debug-port` | 1104 | 1115 | * `--inspect-publish-uid` | |
Collapse file Copy file name to clipboardExpand all lines: doc/node.1 +6Lines changed: 6 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -232,6 +232,12 @@ Specify the | 232 | 232 | as a custom loader, to load | 233 | 233 | .Fl -experimental-modules . | 234 | 234 | . | | 235 | +.It Fl -insecure-http-parser | | 236 | +Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow | | 237 | +interoperability with non-conformant HTTP implementations. It may also allow | | 238 | +request smuggling and other HTTP attacks that rely on invalid headers being | | 239 | +accepted. Avoid using this option. | | 240 | +. | 235 | 241 | .It Fl -max-http-header-size Ns = Ns Ar size | 236 | 242 | Specify the maximum size of HTTP headers in bytes. Defaults to 8KB. | 237 | 243 | . | |
Collapse file Copy file name to clipboardExpand all lines: lib/_http_client.js +3-1Lines changed: 3 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -32,6 +32,7 @@ const { | 32 | 32 | freeParser, | 33 | 33 | parsers, | 34 | 34 | HTTPParser, | | 35 | + isLenient, | 35 | 36 | prepareError, | 36 | 37 | } = require('_http_common'); | 37 | 38 | const { OutgoingMessage } = require('_http_outgoing'); | @@ -655,7 +656,8 @@ function tickOnSocket(req, socket) { | 655 | 656 | req.socket = socket; | 656 | 657 | req.connection = socket; | 657 | 658 | parser.initialize(HTTPParser.RESPONSE, | 658 | | - new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req)); | | 659 | + new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req), | | 660 | + isLenient()); | 659 | 661 | parser.socket = socket; | 660 | 662 | parser.outgoing = req; | 661 | 663 | req.parser = parser; | |
Collapse file Copy file name to clipboardExpand all lines: lib/_http_common.js +12Lines changed: 12 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -29,6 +29,7 @@ const { getOptionValue } = require('internal/options'); | 29 | 29 | const { methods, HTTPParser } = | 30 | 30 | getOptionValue('--http-parser') === 'legacy' ? | 31 | 31 | internalBinding('http_parser') : internalBinding('http_parser_llhttp'); | | 32 | +const insecureHTTPParser = getOptionValue('--insecure-http-parser'); | 32 | 33 |
| 33 | 34 | const FreeList = require('internal/freelist'); | 34 | 35 | const incoming = require('_http_incoming'); | @@ -238,6 +239,16 @@ function prepareError(err, parser, rawPacket) { | 238 | 239 | err.message = `Parse Error: ${err.reason}`; | 239 | 240 | } | 240 | 241 |
| | 242 | +let warnedLenient = false; | | 243 | + | | 244 | +function isLenient() { | | 245 | + if (insecureHTTPParser && !warnedLenient) { | | 246 | + warnedLenient = true; | | 247 | + process.emitWarning('Using insecure HTTP parsing'); | | 248 | + } | | 249 | + return insecureHTTPParser; | | 250 | +} | | 251 | + | 241 | 252 | module.exports = { | 242 | 253 | _checkInvalidHeaderChar: checkInvalidHeaderChar, | 243 | 254 | _checkIsHttpToken: checkIsHttpToken, | @@ -250,5 +261,6 @@ module.exports = { | 250 | 261 | parsers, | 251 | 262 | kIncomingMessage, | 252 | 263 | HTTPParser, | | 264 | + isLenient, | 253 | 265 | prepareError, | 254 | 266 | }; |
Collapse file Copy file name to clipboardExpand all lines: lib/_http_server.js +3-1Lines changed: 3 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -39,6 +39,7 @@ const { | 39 | 39 | chunkExpression, | 40 | 40 | kIncomingMessage, | 41 | 41 | HTTPParser, | | 42 | + isLenient, | 42 | 43 | _checkInvalidHeaderChar: checkInvalidHeaderChar, | 43 | 44 | prepareError, | 44 | 45 | } = require('_http_common'); | @@ -385,7 +386,8 @@ function connectionListenerInternal(server, socket) { | 385 | 386 | // https://github.com/nodejs/node/pull/21313 | 386 | 387 | parser.initialize( | 387 | 388 | HTTPParser.REQUEST, | 388 | | - new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket) | | 389 | + new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket), | | 390 | + isLenient(), | 389 | 391 | ); | 390 | 392 | parser.socket = socket; | 391 | 393 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/node_http_parser_impl.h +5-2Lines changed: 5 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -501,6 +501,7 @@ class Parser : public AsyncWrap, public StreamListener { | 501 | 501 |
| 502 | 502 | static void Initialize(const FunctionCallbackInfo<Value>& args) { | 503 | 503 | Environment* env = Environment::GetCurrent(args); | | 504 | + bool lenient = args[2]->IsTrue(); | 504 | 505 |
| 505 | 506 | CHECK(args[0]->IsInt32()); | 506 | 507 | CHECK(args[1]->IsObject()); | @@ -521,7 +522,7 @@ class Parser : public AsyncWrap, public StreamListener { | 521 | 522 |
| 522 | 523 | parser->set_provider_type(provider); | 523 | 524 | parser->AsyncReset(args[1].As<Object>()); | 524 | | - parser->Init(type); | | 525 | + parser->Init(type, lenient); | 525 | 526 | } | 526 | 527 |
| 527 | 528 | template <bool should_pause> | @@ -805,12 +806,14 @@ class Parser : public AsyncWrap, public StreamListener { | 805 | 806 | } | 806 | 807 |
| 807 | 808 |
| 808 | | - void Init(parser_type_t type) { | | 809 | + void Init(parser_type_t type, bool lenient) { | 809 | 810 | #ifdef NODE_EXPERIMENTAL_HTTP | 810 | 811 | llhttp_init(&parser_, type, &settings); | | 812 | + llhttp_set_lenient(&parser_, lenient); | 811 | 813 | header_nread_ = 0; | 812 | 814 | #else /* !NODE_EXPERIMENTAL_HTTP */ | 813 | 815 | http_parser_init(&parser_, type); | | 816 | + parser_.lenient_http_headers = lenient; | 814 | 817 | #endif /* NODE_EXPERIMENTAL_HTTP */ | 815 | 818 | url_.Reset(); | 816 | 819 | status_message_.Reset(); | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.cc +4Lines changed: 4 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -416,6 +416,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | 416 | 416 | "(default: 120000)", | 417 | 417 | &EnvironmentOptions::http_server_default_timeout, | 418 | 418 | kAllowedInEnvironment); | | 419 | + AddOption("--insecure-http-parser", | | 420 | + "Use an insecure HTTP parser that accepts invalid HTTP headers", | | 421 | + &EnvironmentOptions::insecure_http_parser, | | 422 | + kAllowedInEnvironment); | 419 | 423 | AddOption("--input-type", | 420 | 424 | "set module type for string input", | 421 | 425 | &EnvironmentOptions::module_type, | |
Collapse file Copy file name to clipboardExpand all lines: src/node_options.h +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -159,6 +159,8 @@ class EnvironmentOptions : public Options { | 159 | 159 | bool print_eval = false; | 160 | 160 | bool force_repl = false; | 161 | 161 |
| | 162 | + bool insecure_http_parser = false; | | 163 | + | 162 | 164 | bool tls_min_v1_0 = false; | 163 | 165 | bool tls_min_v1_1 = false; | 164 | 166 | bool tls_min_v1_2 = false; | |
|