mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
http: llhttp opt-in insecure HTTP header parsing
Allow insecure HTTP header parsing. Make clear it is insecure. See: - https://github.com/nodejs/node/pull/30553 - https://github.com/nodejs/node/issues/27711#issuecomment-556265881 - https://github.com/nodejs/node/issues/30515 PR-URL: https://github.com/nodejs/node/pull/30567 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>
This commit is contained in:
1 parent
d7b8ae72d9
commit
02a0c74861
8 files changed
+47
-4
No files matched your search
@@ -419,6 +419,16 @@ added: v9.0.0
|
||||
Specify the `module` of a custom [experimental ECMAScript Module loader][].
|
||||
`module` may be either a path to a file, or an ECMAScript Module name.
|
||||
|
||||
### `--insecure-http-parser`
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow
|
||||
interoperability with non-conformant HTTP implementations. It may also allow
|
||||
request smuggling and other HTTP attacks that rely on invalid headers being
|
||||
accepted. Avoid using this option.
|
||||
|
||||
### `--max-http-header-size=size`
|
||||
<!-- YAML
|
||||
added: v11.6.0
|
||||
@@ -1064,6 +1074,7 @@ Node.js options that are allowed are:
|
||||
* `--http-parser`
|
||||
* `--icu-data-dir`
|
||||
* `--input-type`
|
||||
* `--insecure-http-parser`
|
||||
* `--inspect-brk`
|
||||
* `--inspect-port`, `--debug-port`
|
||||
* `--inspect-publish-uid`
|
||||
|
||||
@@ -213,6 +213,12 @@ Specify the
|
||||
.Ar module
|
||||
to use as a custom module loader.
|
||||
.
|
||||
.It Fl -insecure-http-parser
|
||||
Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow
|
||||
interoperability with non-conformant HTTP implementations. It may also allow
|
||||
request smuggling and other HTTP attacks that rely on invalid headers being
|
||||
accepted. Avoid using this option.
|
||||
.
|
||||
.It Fl -max-http-header-size Ns = Ns Ar size
|
||||
Specify the maximum size of HTTP headers in bytes. Defaults to 8KB.
|
||||
.
|
||||
|
||||
+3
-1
@@ -39,6 +39,7 @@ const {
|
||||
freeParser,
|
||||
parsers,
|
||||
HTTPParser,
|
||||
isLenient,
|
||||
prepareError,
|
||||
} = require('_http_common');
|
||||
const { OutgoingMessage } = require('_http_outgoing');
|
||||
@@ -676,7 +677,8 @@ function tickOnSocket(req, socket) {
|
||||
req.socket = socket;
|
||||
parser.initialize(HTTPParser.RESPONSE,
|
||||
new HTTPClientAsyncResource('HTTPINCOMINGMESSAGE', req),
|
||||
req.maxHeaderSize || 0);
|
||||
req.maxHeaderSize || 0,
|
||||
isLenient());
|
||||
parser.socket = socket;
|
||||
parser.outgoing = req;
|
||||
req.parser = parser;
|
||||
|
||||
@@ -28,6 +28,8 @@ const {
|
||||
const { setImmediate } = require('timers');
|
||||
|
||||
const { methods, HTTPParser } = internalBinding('http_parser');
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const insecureHTTPParser = getOptionValue('--insecure-http-parser');
|
||||
|
||||
const FreeList = require('internal/freelist');
|
||||
const incoming = require('_http_incoming');
|
||||
@@ -237,6 +239,16 @@ function prepareError(err, parser, rawPacket) {
|
||||
err.message = `Parse Error: ${err.reason}`;
|
||||
}
|
||||
|
||||
let warnedLenient = false;
|
||||
|
||||
function isLenient() {
|
||||
if (insecureHTTPParser && !warnedLenient) {
|
||||
warnedLenient = true;
|
||||
process.emitWarning('Using insecure HTTP parsing');
|
||||
}
|
||||
return insecureHTTPParser;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
_checkInvalidHeaderChar: checkInvalidHeaderChar,
|
||||
_checkIsHttpToken: checkIsHttpToken,
|
||||
@@ -249,5 +261,6 @@ module.exports = {
|
||||
parsers,
|
||||
kIncomingMessage,
|
||||
HTTPParser,
|
||||
isLenient,
|
||||
prepareError,
|
||||
};
|
||||
+3
-1
@@ -39,6 +39,7 @@ const {
|
||||
chunkExpression,
|
||||
kIncomingMessage,
|
||||
HTTPParser,
|
||||
isLenient,
|
||||
_checkInvalidHeaderChar: checkInvalidHeaderChar,
|
||||
prepareError,
|
||||
} = require('_http_common');
|
||||
@@ -410,7 +411,8 @@ function connectionListenerInternal(server, socket) {
|
||||
parser.initialize(
|
||||
HTTPParser.REQUEST,
|
||||
new HTTPServerAsyncResource('HTTPINCOMINGMESSAGE', socket),
|
||||
server.maxHeaderSize || 0
|
||||
server.maxHeaderSize || 0,
|
||||
isLenient(),
|
||||
);
|
||||
parser.socket = socket;
|
||||
|
||||
|
||||
@@ -486,11 +486,13 @@ class Parser : public AsyncWrap, public StreamListener {
|
||||
|
||||
static void Initialize(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
bool lenient = args[3]->IsTrue();
|
||||
|
||||
uint64_t max_http_header_size = 0;
|
||||
|
||||
CHECK(args[0]->IsInt32());
|
||||
CHECK(args[1]->IsObject());
|
||||
|
||||
if (args.Length() > 2) {
|
||||
CHECK(args[2]->IsNumber());
|
||||
max_http_header_size = args[2].As<Number>()->Value();
|
||||
@@ -515,7 +517,7 @@ class Parser : public AsyncWrap, public StreamListener {
|
||||
|
||||
parser->set_provider_type(provider);
|
||||
parser->AsyncReset(args[1].As<Object>());
|
||||
parser->Init(type, max_http_header_size);
|
||||
parser->Init(type, max_http_header_size, lenient);
|
||||
}
|
||||
|
||||
template <bool should_pause>
|
||||
@@ -762,8 +764,9 @@ class Parser : public AsyncWrap, public StreamListener {
|
||||
}
|
||||
|
||||
|
||||
void Init(llhttp_type_t type, uint64_t max_http_header_size) {
|
||||
void Init(llhttp_type_t type, uint64_t max_http_header_size, bool lenient) {
|
||||
llhttp_init(&parser_, type, &settings);
|
||||
llhttp_set_lenient(&parser_, lenient);
|
||||
header_nread_ = 0;
|
||||
url_.Reset();
|
||||
status_message_.Reset();
|
||||
|
||||
@@ -375,6 +375,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
||||
&EnvironmentOptions::heap_snapshot_signal,
|
||||
kAllowedInEnvironment);
|
||||
AddOption("--http-parser", "", NoOp{}, kAllowedInEnvironment);
|
||||
AddOption("--insecure-http-parser",
|
||||
"use an insecure HTTP parser that accepts invalid HTTP headers",
|
||||
&EnvironmentOptions::insecure_http_parser,
|
||||
kAllowedInEnvironment);
|
||||
AddOption("--input-type",
|
||||
"set module type for string input",
|
||||
&EnvironmentOptions::module_type,
|
||||
|
||||
@@ -158,6 +158,8 @@ class EnvironmentOptions : public Options {
|
||||
bool print_eval = false;
|
||||
bool force_repl = false;
|
||||
|
||||
bool insecure_http_parser = false;
|
||||
|
||||
bool tls_min_v1_0 = false;
|
||||
bool tls_min_v1_1 = false;
|
||||
bool tls_min_v1_2 = false;
|
||||
|
||||
Reference in new issue
Block a user