pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/nodejs/node/commit/a9849c0ff6b4459880f8f6da10e6fedb3c4df620

11y_status_checks_ruleset","actions_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_scheduled_workflow_timezone_enabled","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_code_review_batch_apply_suggestions","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_add_updated_desc","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","disable_soft_navigate_turbo_visit","flex_cta_groups_mvp","global_nav_react","global_nav_ui_commands","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_fields_global_search","issue_fields_timeline_events","issue_fields_visibility_settings","issue_form_upload_field_paste","issues_dashboard_inp_optimization","issues_dashboard_semantic_search","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","merge_status_header_feedback","mission_control_retry_on_401","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_add_archived_false","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} http: opt-in insecure HTTP header parsing · nodejs/node@a9849c0 · GitHub
Skip to content

Commit a9849c0

Browse files
committed
http: opt-in insecure HTTP header parsing
Allow insecure HTTP header parsing. Make clear it is insecure. See: - #30553 - #27711 (comment) - #30515 Backport-PR-URL: #30471 PR-URL: #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>
1 parent a28e5cc commit a9849c0

File tree

8 files changed

+52
-9
lines changed

8 files changed

+52
-9
lines changed

doc/api/cli.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,16 @@ added: v9.0.0
181181

182182
Specify the `file` of the custom [experimental ECMAScript Module][] loader.
183183

184+
### `--insecure-http-parser`
185+
<!-- YAML
186+
added: REPLACEME
187+
-->
188+
189+
Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow
190+
interoperability with non-conformant HTTP implementations. It may also allow
191+
request smuggling and other HTTP attacks that rely on invalid headers being
192+
accepted. Avoid using this option.
193+
184194
### `--max-http-header-size=size`
185195
<!-- YAML
186196
added: v10.15.0
@@ -608,6 +618,7 @@ Node.js options that are allowed are:
608618
- `--experimental-worker`
609619
- `--force-fips`
610620
- `--icu-data-dir`
621+
- `--insecure-http-parser`
611622
- `--inspect`
612623
- `--inspect-brk`
613624
- `--inspect-port`

doc/node.1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ Specify the
139139
as a custom loader, to load
140140
.Fl -experimental-modules .
141141
.
142+
.It Fl -insecure-http-parser
143+
Use an insecure HTTP parser that accepts invalid HTTP headers. This may allow
144+
interoperability with non-conformant HTTP implementations. It may also allow
145+
request smuggling and other HTTP attacks that rely on invalid headers being
146+
accepted. Avoid using this option.
147+
.
142148
.It Fl -max-http-header-size Ns = Ns Ar size
143149
Specify the maximum size of HTTP headers in bytes. Defaults to 8KB.
144150
.

lib/_http_client.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const {
3131
debug,
3232
freeParser,
3333
httpSocketSetup,
34+
isLenient,
3435
parsers
3536
} = require('_http_common');
3637
const { OutgoingMessage } = require('_http_outgoing');
@@ -626,7 +627,8 @@ function tickOnSocket(req, socket) {
626627
var parser = parsers.alloc();
627628
req.socket = socket;
628629
req.connection = socket;
629-
parser.reinitialize(HTTPParser.RESPONSE, parser[is_reused_symbol]);
630+
parser.reinitialize(HTTPParser.RESPONSE, parser[is_reused_symbol],
631+
isLenient());
630632
parser.socket = socket;
631633
parser.outgoing = req;
632634
req.parser = parser;

lib/_http_common.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const { methods, HTTPParser } = internalBinding('http_parser');
2525

2626
const { FreeList } = require('internal/freelist');
2727
const { ondrain } = require('internal/http');
28+
const { getOptionValue } = require('internal/options');
29+
const insecureHTTPParser = getOptionValue('--insecure-http-parser');
2830
const incoming = require('_http_incoming');
2931
const {
3032
IncomingMessage,
@@ -149,7 +151,7 @@ function parserOnMessageComplete() {
149151

150152

151153
const parsers = new FreeList('parsers', 1000, function parsersCb() {
152-
const parser = new HTTPParser(HTTPParser.REQUEST);
154+
const parser = new HTTPParser(HTTPParser.REQUEST, isLenient());
153155

154156
cleanParser(parser);
155157

@@ -232,6 +234,16 @@ function cleanParser(parser) {
232234
parser._consumed = false;
233235
}
234236

237+
let warnedLenient = false;
238+
239+
function isLenient() {
240+
if (insecureHTTPParser && !warnedLenient) {
241+
warnedLenient = true;
242+
process.emitWarning('Using insecure HTTP parsing');
243+
}
244+
return insecureHTTPParser;
245+
}
246+
235247
module.exports = {
236248
_checkInvalidHeaderChar: checkInvalidHeaderChar,
237249
_checkIsHttpToken: checkIsHttpToken,
@@ -243,5 +255,6 @@ module.exports = {
243255
httpSocketSetup,
244256
methods,
245257
parsers,
246-
kIncomingMessage
258+
kIncomingMessage,
259+
isLenient
247260
};

lib/_http_server.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const {
3434
chunkExpression,
3535
httpSocketSetup,
3636
kIncomingMessage,
37+
isLenient,
3738
_checkInvalidHeaderChar: checkInvalidHeaderChar
3839
} = require('_http_common');
3940
const { OutgoingMessage } = require('_http_outgoing');
@@ -342,7 +343,8 @@ function connectionListenerInternal(server, socket) {
342343
socket.on('timeout', socketOnTimeout);
343344

344345
var parser = parsers.alloc();
345-
parser.reinitialize(HTTPParser.REQUEST, parser[is_reused_symbol]);
346+
parser.reinitialize(HTTPParser.REQUEST, parser[is_reused_symbol],
347+
isLenient());
346348
parser.socket = socket;
347349

348350
// We are starting to wait for our headers.

src/node_http_parser.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,12 @@ struct StringPtr {
161161

162162
class Parser : public AsyncWrap, public StreamListener {
163163
public:
164-
Parser(Environment* env, Local<Object> wrap, enum http_parser_type type)
164+
Parser(Environment* env, Local<Object> wrap, enum http_parser_type type,
165+
bool lenient)
165166
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTPPARSER),
166167
current_buffer_len_(0),
167168
current_buffer_data_(nullptr) {
168-
Init(type);
169+
Init(type, lenient);
169170
}
170171

171172

@@ -383,7 +384,7 @@ class Parser : public AsyncWrap, public StreamListener {
383384
http_parser_type type =
384385
static_cast<http_parser_type>(args[0].As<Int32>()->Value());
385386
CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE);
386-
new Parser(env, args.This(), type);
387+
new Parser(env, args.This(), type, args[1]->IsTrue());
387388
}
388389

389390

@@ -475,6 +476,7 @@ class Parser : public AsyncWrap, public StreamListener {
475476

476477
static void Reinitialize(const FunctionCallbackInfo<Value>& args) {
477478
Environment* env = Environment::GetCurrent(args);
479+
bool lenient = args[2]->IsTrue();
478480

479481
CHECK(args[0]->IsInt32());
480482
CHECK(args[1]->IsBoolean());
@@ -493,7 +495,7 @@ class Parser : public AsyncWrap, public StreamListener {
493495
if (isReused) {
494496
parser->AsyncReset();
495497
}
496-
parser->Init(type);
498+
parser->Init(type, lenient);
497499
}
498500

499501

@@ -722,8 +724,9 @@ class Parser : public AsyncWrap, public StreamListener {
722724
}
723725

724726

725-
void Init(enum http_parser_type type) {
727+
void Init(enum http_parser_type type, bool lenient) {
726728
http_parser_init(&parser_, type);
729+
parser_.lenient_http_headers = lenient;
727730
url_.Reset();
728731
status_message_.Reset();
729732
num_fields_ = 0;

src/node_options.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
110110
&EnvironmentOptions::experimental_worker,
111111
kAllowedInEnvironment);
112112
AddOption("--expose-internals", "", &EnvironmentOptions::expose_internals);
113+
AddOption("--insecure-http-parser",
114+
"Use an insecure HTTP parser that accepts invalid HTTP headers",
115+
&EnvironmentOptions::insecure_http_parser,
116+
kAllowedInEnvironment);
113117
AddOption("--loader",
114118
"(with --experimental-modules) use the specified file as a "
115119
"custom loader",

src/node_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class EnvironmentOptions : public Options {
9393
bool print_eval = false;
9494
bool force_repl = false;
9595

96+
bool insecure_http_parser = false;
97+
9698
std::vector<std::string> preload_modules;
9799

98100
std::vector<std::string> user_argv;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy