Skip to content

Commit daefd2f

Browse files
phlaxyanavlasovbotengyao
authored
[bp/1.36] Security patches 25q4 (#42374)
* Security fixes: - [CVE-2025-64527](GHSA-mp85-7mrq-r866): Envoy crashes when JWT authentication is configured with the remote JWKS fetching - [CVE-2025-66220](GHSA-rwjg-c3h2-f57p): TLS certificate matcher for `match_typed_subject_alt_names` may incorrectly treat certificates containing an embedded null byte - [CVE-2025-64763](GHSA-rj35-4m94-77jh): Potential request smuggling from early data after the CONNECT up|grade --------- Signed-off-by: Greg Greenway <[email protected]> Signed-off-by: Yan Avlasov <[email protected]> Signed-off-by: Boteng Yao <[email protected]> Signed-off-by: Ryan Northey <[email protected]> Co-authored-by: Yan Avlasov <[email protected]> Co-authored-by: Boteng Yao <[email protected]>
1 parent 495e2a6 commit daefd2f

File tree

16 files changed

+249
-7
lines changed

16 files changed

+249
-7
lines changed

changelogs/current.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ behavior_changes:
77
The dynamic module ABI has been updated to support streaming body manipulation. This change also
88
fixed potential incorrect behavior when access or modify the request or response body. See
99
https://github.com/envoyproxy/envoy/issues/40918 for more details.
10+
- area: http
11+
change: |
12+
Added runtime flag ``envoy.reloadable_features.reject_early_connect_data`` to reject ``CONNECT`` requests
13+
that receive data before Envoy sent a ``200`` response to the client. While this is not a strictly compliant behavior
14+
it is very common as a latency reducing measure. As such the option is disabled by default.
1015
1116
minor_behavior_changes:
1217
# *Changes that may cause incompatibilities for some users, but should not for most*
@@ -22,6 +27,13 @@ bug_fixes:
2227
change: |
2328
Fixed a connection leak in the TCP proxy when the ``receive_before_connect`` feature is enabled and the
2429
downstream connection closes before the upstream connection is established.
30+
- area: tls
31+
change: |
32+
Fixed an issue where SANs of type ``OTHERNAME`` in a TLS cert were truncated if there was
33+
an embedded null octet, leading to incorrect SAN validation.
34+
- area: http
35+
change: |
36+
Fixed a remote ``jwt_auth`` token fetch crash with two or more auth headers when ``allow_missing_or_failed`` is set.
2537
2638
removed_config_or_runtime:
2739
# *Normally occurs at the end of the* :ref:`deprecation period <deprecated>`

changelogs/summary.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
* Security fixes:
3+
- CVE-2025-64527: Envoy crashes when JWT authentication is configured with the remote JWKS fetching
4+
- CVE-2025-66220: TLS certificate matcher for `match_typed_subject_alt_names` may incorrectly treat certificates containing an embedded null byte
5+
- CVE-2025-64763: Potential request smuggling from early data after the CONNECT upgrade

docs/root/configuration/http/http_conn_man/response_code_details.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Below are the list of reasons the HttpConnectionManager or Router filter may sen
2525
downstream_remote_disconnect, The client disconnected unexpectedly.
2626
duration_timeout, The max connection duration was exceeded.
2727
direct_response, A direct response was generated by the router filter.
28+
early_connect_data, Data was received for a CONNECT request before 200 response headers were sent.
2829
filter_added_invalid_request_data, A filter added request data at the wrong stage in the filter chain.
2930
filter_added_invalid_response_data, A filter added response data at the wrong stage in the filter chain.
3031
filter_chain_not_found, The request was rejected due to no matching filter chain.

envoy/stream_info/stream_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ struct ResponseCodeDetailValues {
248248
const std::string FilterAddedInvalidRequestData = "filter_added_invalid_request_data";
249249
// A filter called addDecodedData at the wrong point in the filter chain.
250250
const std::string FilterAddedInvalidResponseData = "filter_added_invalid_response_data";
251+
// Data was received for a CONNECT request before 200 response headers were sent.
252+
const std::string EarlyConnectData = "early_connect_data";
251253
// Changes or additions to details should be reflected in
252254
// docs/root/configuration/http/http_conn_man/response_code_details.rst
253255
};

source/common/router/router.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,19 @@ uint64_t Filter::calculateEffectiveBufferLimit() const {
956956
return std::numeric_limits<uint64_t>::max();
957957
}
958958

959+
bool Filter::isEarlyConnectData() {
960+
return downstream_headers_ != nullptr && Http::HeaderUtility::isConnect(*downstream_headers_) &&
961+
!downstream_response_started_ &&
962+
Runtime::runtimeFeatureEnabled("envoy.reloadable_features.reject_early_connect_data");
963+
}
964+
959965
Http::FilterDataStatus Filter::decodeData(Buffer::Instance& data, bool end_stream) {
966+
ENVOY_STREAM_LOG(debug, "router decoding data: {}", *callbacks_, data.length());
967+
if (data.length() > 0 && isEarlyConnectData()) {
968+
callbacks_->sendLocalReply(Http::Code::BadRequest, "", nullptr, absl::nullopt,
969+
StreamInfo::ResponseCodeDetails::get().EarlyConnectData);
970+
return Http::FilterDataStatus::StopIterationNoBuffer;
971+
}
960972
// upstream_requests_.size() cannot be > 1 because that only happens when a per
961973
// try timeout occurs with hedge_on_per_try_timeout enabled but the per
962974
// try timeout timer is not started until onRequestComplete(). It could be zero

source/common/router/router.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ class Filter : Logger::Loggable<Logger::Id::router>,
625625
// Process Orca Load Report if necessary (e.g. cluster has lrsReportMetricNames).
626626
void maybeProcessOrcaLoadReport(const Envoy::Http::HeaderMap& headers_or_trailers,
627627
UpstreamRequest& upstream_request);
628+
bool isEarlyConnectData();
628629

629630
RetryStatePtr retry_state_;
630631
const FilterConfigSharedPtr config_;

source/common/runtime/runtime_features.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ FALSE_RUNTIME_GUARD(envoy_restart_features_use_cached_grpc_client_for_xds);
192192
FALSE_RUNTIME_GUARD(envoy_reloadable_features_http_11_proxy_connect_legacy_format);
193193
// TODO(tsaarni): Flip to true after prod testing or remove.
194194
FALSE_RUNTIME_GUARD(envoy_reloadable_features_fixed_heap_use_allocated);
195+
// TODO(yavlasov): Enabling by default will be hugely disruptive to existing traffic.
196+
// Replace with a config option (default off) post CVE release.
197+
FALSE_RUNTIME_GUARD(envoy_reloadable_features_reject_early_connect_data);
195198

196199
// Block of non-boolean flags. Use of int flags is deprecated. Do not add more.
197200
ABSL_FLAG(uint64_t, re2_max_program_size_error_level, 100, ""); // NOLINT

source/common/tls/utility.cc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,22 +339,24 @@ std::string Utility::generalNameAsString(const GENERAL_NAME* general_name) {
339339
break;
340340
}
341341
case V_ASN1_BMPSTRING: {
342-
// `ASN1_BMPSTRING` is encoded using `UCS-4`, which needs conversion to UTF-8.
342+
// `ASN1_BMPSTRING` is encoded using `UTF-16`, which needs conversion to UTF-8.
343343
unsigned char* tmp = nullptr;
344-
if (ASN1_STRING_to_UTF8(&tmp, value->value.bmpstring) < 0) {
344+
int length = ASN1_STRING_to_UTF8(&tmp, value->value.bmpstring);
345+
if (length < 0) {
345346
break;
346347
}
347-
san.assign(reinterpret_cast<const char*>(tmp));
348+
san.assign(reinterpret_cast<const char*>(tmp), length);
348349
OPENSSL_free(tmp);
349350
break;
350351
}
351352
case V_ASN1_UNIVERSALSTRING: {
352353
// `ASN1_UNIVERSALSTRING` is encoded using `UCS-4`, which needs conversion to UTF-8.
353354
unsigned char* tmp = nullptr;
354-
if (ASN1_STRING_to_UTF8(&tmp, value->value.universalstring) < 0) {
355+
int length = ASN1_STRING_to_UTF8(&tmp, value->value.universalstring);
356+
if (length < 0) {
355357
break;
356358
}
357-
san.assign(reinterpret_cast<const char*>(tmp));
359+
san.assign(reinterpret_cast<const char*>(tmp), length);
358360
OPENSSL_free(tmp);
359361
break;
360362
}

source/extensions/filters/http/common/jwks_fetcher.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class JwksFetcherImpl : public JwksFetcher,
3535
request_->cancel();
3636
ENVOY_LOG(debug, "fetch pubkey [uri = {}]: canceled", remote_jwks_.http_uri().uri());
3737
}
38+
complete_ = true;
3839
reset();
3940
}
4041

@@ -129,8 +130,10 @@ class JwksFetcherImpl : public JwksFetcher,
129130
Http::AsyncClient::Request* request_{};
130131

131132
void reset() {
132-
request_ = nullptr;
133-
receiver_ = nullptr;
133+
if (complete_) {
134+
request_ = nullptr;
135+
receiver_ = nullptr;
136+
}
134137
}
135138
};
136139
} // namespace

source/extensions/filters/http/jwt_authn/authenticator.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,12 @@ void AuthenticatorImpl::startVerify() {
288288
if (jwks_data_->getJwtProvider().has_remote_jwks()) {
289289
if (!fetcher_) {
290290
fetcher_ = create_jwks_fetcher_cb_(cm_, jwks_data_->getJwtProvider().remote_jwks());
291+
} else {
292+
// Cancel the previous fetch to reset if it is pending or not completed.
293+
// At most one outstanding request may be in-flight, and it is possible that
294+
// a new call is from the callback itself, which in-turn will reset the
295+
// fetcher afterwards.
296+
fetcher_->cancel();
291297
}
292298
fetcher_->fetch(*parent_span_, *this);
293299
return;

0 commit comments

Comments
 (0)