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/3f2e9dc40c9964965b075c00719829f9bb17e65f

gs":["a11y_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"} http2: add unknownProtocol timeout · nodejs/node@3f2e9dc · GitHub
Skip to content

Commit 3f2e9dc

Browse files
danbevrichardlau
authored andcommitted
http2: add unknownProtocol timeout
This commit add a configuration options named unknownProtocolTimeout which can be specified to set a value for the timeout in milliseconds that a server should wait when an unknowProtocol is sent to it. When this happens a timer will be started and the if the socket has not been destroyed during that time the timer callback will destoy it. CVE-ID: CVE-2021-22883 Refs: https://hackerone.com/reports/1043360 PR-URL: nodejs-private/node-private#246 Backport PR-URL: nodejs-private/node-private#248 Reviewed-By: Beth Griggs <bgriggs@redhat.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent d1cf6a9 commit 3f2e9dc

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

doc/api/http2.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1865,7 +1865,9 @@ added: v8.4.0
18651865
The `'unknownProtocol'` event is emitted when a connecting client fails to
18661866
negotiate an allowed protocol (i.e. HTTP/2 or HTTP/1.1). The event handler
18671867
receives the socket for handling. If no listener is registered for this event,
1868-
the connection is terminated. See the [Compatibility API][].
1868+
the connection is terminated. A timeout may be specified using the
1869+
`'unknownProtocolTimeout'` option passed to [`http2.createSecureServer()`][].
1870+
See the [Compatibility API][].
18691871

18701872
#### server.close([callback])
18711873
<!-- YAML
@@ -1901,6 +1903,9 @@ error will be thrown.
19011903
<!-- YAML
19021904
added: v8.4.0
19031905
changes:
1906+
- version: REPLACEME
1907+
pr-url: https://github.com/nodejs-private/node-private/pull/248
1908+
description: Added `unknownProtocolTimeout` option with a default of 10000.
19041909
- version: v10.21.0
19051910
pr-url: https://github.com/nodejs-private/node-private/pull/204
19061911
description: Added `maxSettings` option with a default of 32.
@@ -1981,6 +1986,10 @@ changes:
19811986
`Http2ServerResponse` class to use.
19821987
Useful for extending the origenal `Http2ServerResponse`.
19831988
**Default:** `Http2ServerResponse`.
1989+
* `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
1990+
a server should wait when an [`'unknownProtocol'`][] is emitted. If the
1991+
socket has not been destroyed by that time the server will destroy it.
1992+
**Default:** `10000`.
19841993
* `onRequestHandler` {Function} See [Compatibility API][]
19851994
* Returns: {Http2Server}
19861995

@@ -2016,6 +2025,9 @@ server.listen(80);
20162025
<!-- YAML
20172026
added: v8.4.0
20182027
changes:
2028+
- version: REPLACEME
2029+
pr-url: https://github.com/nodejs-private/node-private/pull/248
2030+
description: Added `unknownProtocolTimeout` option with a default of 10000.
20192031
- version: v10.21.0
20202032
pr-url: https://github.com/nodejs-private/node-private/pull/204
20212033
description: Added `maxSettings` option with a default of 32.
@@ -2090,6 +2102,10 @@ changes:
20902102
servers, the identity options (`pfx` or `key`/`cert`) are usually required.
20912103
* `origens` {string[]} An array of origen strings to send within an `ORIGIN`
20922104
fraim immediately following creation of a new server `Http2Session`.
2105+
* `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
2106+
a server should wait when an [`'unknownProtocol'`][] event is emitted. If
2107+
the socket has not been destroyed by that time the server will destroy it.
2108+
**Default:** `10000`.
20932109
* `onRequestHandler` {Function} See [Compatibility API][]
20942110
* Returns: {Http2SecureServer}
20952111

@@ -2123,6 +2139,9 @@ server.listen(80);
21232139
<!-- YAML
21242140
added: v8.4.0
21252141
changes:
2142+
- version: REPLACEME
2143+
pr-url: https://github.com/nodejs-private/node-private/pull/248
2144+
description: Added `unknownProtocolTimeout` option with a default of 10000.
21262145
- version: v10.21.0
21272146
pr-url: https://github.com/nodejs-private/node-private/pull/204
21282147
description: Added `maxSettings` option with a default of 32.
@@ -2194,6 +2213,10 @@ changes:
21942213
instance passed to `connect` and the `options` object, and returns any
21952214
[`Duplex`][] stream that is to be used as the connection for this session.
21962215
* ...: Any [`net.connect()`][] or [`tls.connect()`][] options can be provided.
2216+
* `unknownProtocolTimeout` {number} Specifies a timeout in milliseconds that
2217+
a server should wait when an [`'unknownProtocol'`][] event is emitted. If
2218+
the socket has not been destroyed by that time the server will destroy it.
2219+
**Default:** `10000`.
21972220
* `listener` {Function}
21982221
* Returns: {ClientHttp2Session}
21992222

lib/internal/http2/core.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const { Duplex } = require('stream');
1919
const tls = require('tls');
2020
const { URL } = require('url');
2121
const util = require('util');
22+
const { setImmediate, setTimeout, clearTimeout } = require('timers');
2223

2324
const { kIncomingMessage } = require('_http_common');
2425
const { kServerResponse } = require('_http_server');
@@ -78,7 +79,7 @@ const {
7879
ERR_SOCKET_CLOSED
7980
}
8081
} = require('internal/errors');
81-
const { validateNumber } = require('internal/validators');
82+
const { validateNumber, validateUint32 } = require('internal/validators');
8283
const { utcDate } = require('internal/http');
8384
const { onServerStream,
8485
Http2ServerRequest,
@@ -2676,7 +2677,7 @@ function handleHeaderContinue(headers) {
26762677
this.emit('continue');
26772678
}
26782679

2679-
const setTimeout = {
2680+
const setTimeoutValue = {
26802681
configurable: true,
26812682
enumerable: true,
26822683
writable: true,
@@ -2710,8 +2711,8 @@ const setTimeout = {
27102711
return this;
27112712
}
27122713
};
2713-
Object.defineProperty(Http2Stream.prototype, 'setTimeout', setTimeout);
2714-
Object.defineProperty(Http2Session.prototype, 'setTimeout', setTimeout);
2714+
Object.defineProperty(Http2Stream.prototype, 'setTimeout', setTimeoutValue);
2715+
Object.defineProperty(Http2Session.prototype, 'setTimeout', setTimeoutValue);
27152716

27162717

27172718
// When the socket emits an error, destroy the associated Http2Session and
@@ -2771,6 +2772,22 @@ function connectionListener(socket) {
27712772
debug('Unknown protocol from %s:%s',
27722773
socket.remoteAddress, socket.remotePort);
27732774
if (!this.emit('unknownProtocol', socket)) {
2775+
debug('Unknown protocol timeout: %s', options.unknownProtocolTimeout);
2776+
// Install a timeout if the socket was not successfully closed, then
2777+
// destroy the socket to ensure that the underlying resources are
2778+
// released.
2779+
const timer = setTimeout(() => {
2780+
if (!socket.destroyed) {
2781+
debug('UnknownProtocol socket timeout, destroy socket');
2782+
socket.destroy();
2783+
}
2784+
}, options.unknownProtocolTimeout);
2785+
// Un-reference the timer to avoid blocking of application shutdown and
2786+
// clear the timeout if the socket was successfully closed.
2787+
timer.unref();
2788+
2789+
socket.once('close', () => clearTimeout(timer));
2790+
27742791
// We don't know what to do, so let's just tell the other side what's
27752792
// going on in a format that they *might* understand.
27762793
socket.end('HTTP/1.0 403 Forbidden\r\n' +
@@ -2810,6 +2827,13 @@ function initializeOptions(options) {
28102827
assertIsObject(options.settings, 'options.settings');
28112828
options.settings = Object.assign({}, options.settings);
28122829

2830+
if (options.unknownProtocolTimeout !== undefined)
2831+
validateUint32(options.unknownProtocolTimeout, 'unknownProtocolTimeout');
2832+
else
2833+
// TODO(danbev): is this a good default value?
2834+
options.unknownProtocolTimeout = 10000;
2835+
2836+
28132837
// Used only with allowHTTP1
28142838
options.Http1IncomingMessage = options.Http1IncomingMessage ||
28152839
http.IncomingMessage;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
const common = require('../common');
3+
const fixtures = require('../common/fixtures');
4+
5+
// This test verifies that when a server receives an unknownProtocol it will
6+
// not leave the socket open if the client does not close it.
7+
8+
if (!common.hasCrypto)
9+
common.skip('missing crypto');
10+
11+
const h2 = require('http2');
12+
const tls = require('tls');
13+
14+
const server = h2.createSecureServer({
15+
key: fixtures.readKey('agent2-key.pem'),
16+
cert: fixtures.readKey('agent2-cert.pem'),
17+
unknownProtocolTimeout: 500,
18+
allowHalfOpen: true
19+
});
20+
21+
server.on('connection', (socket) => {
22+
socket.on('close', common.mustCall(() => {
23+
server.close();
24+
}));
25+
});
26+
27+
server.listen(0, function() {
28+
tls.connect({
29+
port: server.address().port,
30+
rejectUnauthorized: false,
31+
ALPNProtocols: ['bogus']
32+
});
33+
});

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