Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3a7a3be

Browse filesBrowse files
sam-githubtargos
authored andcommitted
http: opt-in insecure HTTP header parsing
Allow insecure HTTP header parsing. Make clear it is insecure. See: - #30553 - #27711 (comment) - #30515 PR-URL: #30567 Backport-PR-URL: #30473 Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 25f2df4 commit 3a7a3be
Copy full SHA for 3a7a3be

File tree

Expand file treeCollapse file tree

8 files changed

+46
-4
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+46
-4
lines changed
Open diff view settings
Collapse file

‎doc/api/cli.md‎

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 numberDiff line numberDiff line change
@@ -431,6 +431,16 @@ added: v9.0.0
431431
Specify the `module` of a custom [experimental ECMAScript Module][] loader.
432432
`module` may be either a path to a file, or an ECMAScript Module name.
433433

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+
434444
### `--max-http-header-size=size`
435445
<!-- YAML
436446
added: v11.6.0
@@ -1099,6 +1109,7 @@ Node.js options that are allowed are:
10991109
* `--http-server-default-timeout`
11001110
* `--icu-data-dir`
11011111
* `--input-type`
1112+
* `--insecure-http-parser`
11021113
* `--inspect-brk`
11031114
* `--inspect-port`, `--debug-port`
11041115
* `--inspect-publish-uid`
Collapse file

‎doc/node.1‎

Copy file name to clipboardExpand all lines: doc/node.1
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,12 @@ Specify the
232232
as a custom loader, to load
233233
.Fl -experimental-modules .
234234
.
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+
.
235241
.It Fl -max-http-header-size Ns = Ns Ar size
236242
Specify the maximum size of HTTP headers in bytes. Defaults to 8KB.
237243
.
Collapse file

‎lib/_http_client.js‎

Copy file name to clipboardExpand all lines: lib/_http_client.js
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const {
3232
freeParser,
3333
parsers,
3434
HTTPParser,
35+
isLenient,
3536
prepareError,
3637
} = require('_http_common');
3738
const { OutgoingMessage } = require('_http_outgoing');
@@ -655,7 +656,8 @@ function tickOnSocket(req, socket) {
655656
req.socket = socket;
656657
req.connection = socket;
657658
parser.initialize(HTTPParser.RESPONSE,
658-
new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req));
659+
new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req),
660+
isLenient());
659661
parser.socket = socket;
660662
parser.outgoing = req;
661663
req.parser = parser;
Collapse file

‎lib/_http_common.js‎

Copy file name to clipboardExpand all lines: lib/_http_common.js
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const { getOptionValue } = require('internal/options');
2929
const { methods, HTTPParser } =
3030
getOptionValue('--http-parser') === 'legacy' ?
3131
internalBinding('http_parser') : internalBinding('http_parser_llhttp');
32+
const insecureHTTPParser = getOptionValue('--insecure-http-parser');
3233

3334
const FreeList = require('internal/freelist');
3435
const incoming = require('_http_incoming');
@@ -238,6 +239,16 @@ function prepareError(err, parser, rawPacket) {
238239
err.message = `Parse Error: ${err.reason}`;
239240
}
240241

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+
241252
module.exports = {
242253
_checkInvalidHeaderChar: checkInvalidHeaderChar,
243254
_checkIsHttpToken: checkIsHttpToken,
@@ -250,5 +261,6 @@ module.exports = {
250261
parsers,
251262
kIncomingMessage,
252263
HTTPParser,
264+
isLenient,
253265
prepareError,
254266
};
Collapse file

‎lib/_http_server.js‎

Copy file name to clipboardExpand all lines: lib/_http_server.js
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const {
3939
chunkExpression,
4040
kIncomingMessage,
4141
HTTPParser,
42+
isLenient,
4243
_checkInvalidHeaderChar: checkInvalidHeaderChar,
4344
prepareError,
4445
} = require('_http_common');
@@ -385,7 +386,8 @@ function connectionListenerInternal(server, socket) {
385386
// https://github.com/nodejs/node/pull/21313
386387
parser.initialize(
387388
HTTPParser.REQUEST,
388-
new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket)
389+
new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket),
390+
isLenient(),
389391
);
390392
parser.socket = socket;
391393

Collapse file

‎src/node_http_parser_impl.h‎

Copy file name to clipboardExpand all lines: src/node_http_parser_impl.h
+5-2Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ class Parser : public AsyncWrap, public StreamListener {
501501

502502
static void Initialize(const FunctionCallbackInfo<Value>& args) {
503503
Environment* env = Environment::GetCurrent(args);
504+
bool lenient = args[2]->IsTrue();
504505

505506
CHECK(args[0]->IsInt32());
506507
CHECK(args[1]->IsObject());
@@ -521,7 +522,7 @@ class Parser : public AsyncWrap, public StreamListener {
521522

522523
parser->set_provider_type(provider);
523524
parser->AsyncReset(args[1].As<Object>());
524-
parser->Init(type);
525+
parser->Init(type, lenient);
525526
}
526527

527528
template <bool should_pause>
@@ -805,12 +806,14 @@ class Parser : public AsyncWrap, public StreamListener {
805806
}
806807

807808

808-
void Init(parser_type_t type) {
809+
void Init(parser_type_t type, bool lenient) {
809810
#ifdef NODE_EXPERIMENTAL_HTTP
810811
llhttp_init(&parser_, type, &settings);
812+
llhttp_set_lenient(&parser_, lenient);
811813
header_nread_ = 0;
812814
#else /* !NODE_EXPERIMENTAL_HTTP */
813815
http_parser_init(&parser_, type);
816+
parser_.lenient_http_headers = lenient;
814817
#endif /* NODE_EXPERIMENTAL_HTTP */
815818
url_.Reset();
816819
status_message_.Reset();
Collapse file

‎src/node_options.cc‎

Copy file name to clipboardExpand all lines: src/node_options.cc
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
416416
"(default: 120000)",
417417
&EnvironmentOptions::http_server_default_timeout,
418418
kAllowedInEnvironment);
419+
AddOption("--insecure-http-parser",
420+
"Use an insecure HTTP parser that accepts invalid HTTP headers",
421+
&EnvironmentOptions::insecure_http_parser,
422+
kAllowedInEnvironment);
419423
AddOption("--input-type",
420424
"set module type for string input",
421425
&EnvironmentOptions::module_type,
Collapse file

‎src/node_options.h‎

Copy file name to clipboardExpand all lines: src/node_options.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class EnvironmentOptions : public Options {
159159
bool print_eval = false;
160160
bool force_repl = false;
161161

162+
bool insecure_http_parser = false;
163+
162164
bool tls_min_v1_0 = false;
163165
bool tls_min_v1_1 = false;
164166
bool tls_min_v1_2 = false;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.