Where
AND
-Infinity
0
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

A denial-of-service vulnerability was found in Envoy's HTTP/2 implementation. The attack chains two techniques: an HPACK compression bomb that exploits header compression to amplify a single byte on the wire into a full header allocation on the server (repeated thousands of times per request), and a Slowloris-style hold using a zero-byte HTTP/2 flow-control window that prevents the server from ever freeing the allocated memory.

A remote attacker can exploit this in Envoy's default HTTP/2 configuration to consume and hold large amounts of server memory (up to 32GB in approximately 20 seconds), rendering the server inaccessible.

This vulnerability exists in each server's default HTTP/2 configuration and requires no authentication to exploit.

External Reference: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb

1 / 2
Source: Red Hat
First published (updated )
Severity
4.4
AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:N/A:N

Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.35.11, 1.36.7, 1.37.3, and 1.38.1, a structural flaw was identified in DefaultCertValidator::verifySubjectAltName where the extracted DNS SAN string is cast to a C-style string using .cstr() before being passed to the Utility::dnsNameMatch() algorithm. If the attacker serves a certificate with a dNSName SAN containing an embedded NUL byte, the helper Utility::generalNameAsString captures the complete string including the NUL. However, when .cstr() evaluates it, implicit conversion to absl::stringview inside dnsNameMatch relies on strlen(), prematurely truncating the evaluation context. Envoy evaluates trucated string against the exact required configsan match and returns true, thereby successfully validating the string with the Nul byte for an upstream routing. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.35.11, 1.36.7, 1.37.3, and 1.38.1, destructor of JSON Object results in stack overflow when deeply O(100K) nested objects are present. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.23.0 until 1.35.11, 1.36.7, 1.37.3, and 1.38.1, a vulnerability has been identified in Envoy's zstd decompressor implementation (ZstdDecompressorImpl). When zstd decompression is enabled, processing a specially crafted, highly compressed zstd payload can lead to massive memory allocation. An attacker can exploit this to cause severe memory exhaustion, potentially resulting in an Out-Of-Memory (OOM) kill and Denial of Service (DoS) for the Envoy proxy. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
7.5
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.35.11, 1.36.7, 1.37.3, and 1.38.1, in cases where UDP DNS filter is configured with local resolution containing a name with the length of 255 octets or remote resolution for a name of 255 octets long can complete successfully, a query with such name will result in abnormal process termination. The abnormal process termination is triggered by an invalid runtime precondition that the query name is strictly less than 255 octets, contradicting DNS specification rfc1035#section-2.3.4 that the name can be 255 or less octets. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
7.5
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.34.0 until 1.35.13, 1.36.9, 1.37.5, and 1.38.3, a vulnerability exists in Envoy's TCP StatsD sink (TcpStatsdSink), where the thread-local flusher buffer can be overflowed by exceptionally long statistic names (e.g., >16KiB). During formatting, TcpStatsdSink reserves a single contiguous memory slice of 16KiB (FLUSHSLICESIZEBYTES). If formatting a single metric exceeds the remaining capacity, the flusher initiates a buffer rotation but incorrectly continues to allocate another fixed 16KiB slice. If an attacker can trigger a statistic name longer than 16KiB—for example, by sending an HTTP or gRPC request with an extremely long request path (:path) that is recorded by the grpcstats filter configured with statsforallmethods: true—the flusher will attempt to copy the metric name using memcpy operations beyond the allocated heap buffer boundaries. This leads to a heap write overflow, which can cause immediate denial-of-service (process crash) or potential remote code execution (RCE). This vulnerability is fixed in 1.35.13, 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
7.5
AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:H/A:N

Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.35.11, 1.36.7, 1.37.3, and 1.38.1, Envoy can translate a downstream HTTP/3 request that is complete at the transport layer (HEADERS with FIN / headers-only close) but still carries a nonzero Content-Length into a complete upstream HTTP/1 request with unresolved body debt. In an HTTP/1 upstream deployment where the origin replies before reading the declared body and keeps the connection reusable, the beginning of the next Envoy-generated upstream request can be consumed as the first request's body. The remaining bytes are then parsed by the origin as a new HTTP/1 request. This was reproduced as a route-bypass/desync: direct /pwn was denied by Envoy, but the second downstream H3 stream received the response for backend-parsed GET /pwn HTTP/1.1. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
5.9
Use After Free
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.36.0 until 1.36.9, 1.37.5, and 1.38.3, a Use-After-Free (UAF) vulnerability leading to a sudden segmentation fault exists in Envoy's extauthz HTTP filter when processing per-route authorization overrides concurrently with rapid downstream client disconnects. During standard request lifecycles, Envoy instantiates the extauthz filter with a foundational authorization client object (client). If a matched route dictates a dynamic per-route HTTP or gRPC authorization service override, the filter generates a localized client. In the vulnerable implementation, this transient client aggressively overwrote the default client unique pointer by executing client = std::move(perrouteclient). When a client rapidly establishes and subsequently tears down a stream (such as rapidly refreshing a protected WebSocket endpoint), the downstream triggers the ConnectionManagerImpl::doDeferredStreamDestroy() -> ActiveStream::onResetStream() lifecycle. Envoy immediately sequences Filter::onDestroy() in an attempt to securely abort dispatched asynchronous authorization check transactions via client->cancel(). By destructing the default client abruptly during initiateCall, a memory lifecycle misalignment occurs within the async client manager. The stream teardown fails to reliably track and cancel the dynamically bound asynchronous authorization tasks, orchestrating a sequence where a late asynchronous callback from the network evaluates against a heavily destroyed ActiveStream validation span, generating a UAF process crash. This vulnerability is fixed in 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
6.8
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N

Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.35.11, 1.36.7, 1.37.3, and 1.38.1, the OAuth2 HTTP filter's encrypt()/decrypt() functions use AES-256-CBC without an authentication tag (no HMAC, no AEAD). The /callback endpoint returns HTTP 302 on successful decryption and HTTP 401 on padding failure, creating a padding oracle. An attacker who obtains the encrypted CodeVerifier cookie can recover the plaintext PKCE codeverifier in ~6,200 requests (~100 seconds), then exchange it with a stolen authorization code to obtain the victim's access token. This vulnerability is fixed in 1.35.11, 1.36.7, 1.37.3, and 1.38.1.

First published (updated )
Severity
7.5
Null Pointer Dereference
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.26.0 until 1.35.13, 1.36.9, 1.37.5, and 1.38.3, the envoy.filters.http.grpcstats filter crashes (null pointer dereference / segfault) when a Connect protocol request (Content-Type: application/connect+proto or application/connect+json) hits a directresponse route. A single unauthenticated HTTP request crashes the Envoy process. This vulnerability is fixed in 1.35.13, 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
6.5
Use After Free
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.34.0 until 1.35.13, 1.36.9, 1.37.5, and 1.38.3, Envoy crashes if an extproc server sends a single gRPC message containing multiple, specially crafted ProcessingResponse messages. This can occur when the first response in the batch causes the gRPC stream object to be destroyed, leading to a use-after-free error when Envoy attempts to process subsequent responses in the same gRPC message. This vulnerability is fixed in 1.35.13, 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
7.5
Null Pointer Dereference
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.18.0 until 1.35.13, 1.36.9, 1.37.5, and 1.38.3, the router filter contains a null pointer dereference vulnerability when handling HTTP 303 (See Other) internal redirects for body-less non-GET/HEAD requests. When a POST, PUT, DELETE, or PATCH request without a body is sent to a route configured with internal redirect policy that includes 303 in redirectresponsecodes, and the upstream responds with HTTP 303, the redirect handling code attempts to drain a request body buffer that was never allocated. This results in a segmentation fault that crashes the entire Envoy process. When route configured with internalredirectpolicy including 303 in redirectresponsecodes and upstream must return HTTP 303 response, an unauthenticated attacker can exploit this to cause complete denial of service, terminating all active connections. This vulnerability is fixed in 1.35.13, 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
4.8
AV:A/AC:L/PR:H/UI:N/S:C/C:N/I:L/A:L

Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.34.0 until 1.35.13, 1.36.9, 1.37.5, and 1.38.3, PROXY Protocol v2 header generator emits TLVs beyond the maximum length of 65535 bytes, causing a mismatch between bytes written and the length field in the header. This can result in smuggled bytes on the upstream request. This vulnerability is fixed in 1.35.13, 1.36.9, 1.37.5, and 1.38.3.

First published (updated )
Severity
7.5
Input Validation
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

Calling Utility::getAddressWithPort with a scoped IPv6 addresses causes a crash. This utility is called in the data plane from the originalsrc filter and the dns filter.

Details

The crashing function is Utility::getAddressWithPort. The crash occurs if a string containing a scoped IPv6 address is passed to this function.

This vulnerability affects:

1. The original src filter: If the filter is configured and the original source is a scoped IPv6 address, it will cause a crash. 2. DNS response address resolution: If a DNS response contains a scoped IPv6 address, this will also trigger the crash.

PoC

To reproduce the vulnerability:

1. Method A (Original Src Filter): Configure the original src filter in Envoy and provide a scoped IPv6 address as the original source. 2. Method B (DNS Resolution): Trigger a DNS resolution process within Envoy where the DNS response contains a scoped IPv6 address.

Impact

This is a Denial of Service (DoS) vulnerability. It impacts users who have the original src filter configured or whose Envoy instances resolve addresses from DNS responses that may contain scoped IPv6 addresses.

1 / 2
Source: GitHub
First published (updated )
Severity
8.2
Input Validation
AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N

1. Summary The Envoy RBAC (Role-Based Access Control) filter contains a logic vulnerability in how it validates HTTP headers when multiple values are present for the same header name. Instead of validating each header value individually, Envoy concatenates all values into a single comma-separated string. This behavior allows attackers to bypass RBAC policies—specifically "Deny" rules—by sending duplicate headers, effectively obscuring the malicious value from exact-match mechanisms.

2. Attack Scenario Consider an environment where an administrator wants to block external access to internal resources using a specific header flag.

Configuration The Envoy proxy is configured with a Deny rule to reject requests containing the header internal: true. Rule Type: Exact Match Target: internal header must not equal true.

The Bypass Logic 1. Standard Request (Blocked): Input: internal: true Envoy Processing: Sees string "true". Result: Match found. Request Denied.

2. Exploit Request (Bypassed): Input: http internal: true internal: true Envoy Processing: Concatenates values into "true,true". Matcher Evaluation: Does "true,true" equal "true"? No. Result: The Deny rule fails to trigger. Request Allowed.

3. Implications RBAC Bypass: Remote attackers can bypass configured access controls. Unauthorized Access: Sensitive internal resources or administrative endpoints protected by header-based Deny rules become accessible. Risk: High, particularly for deployments relying on "Exact Match" strategies for security blocking.

4. Reproduction Steps To verify this vulnerability:

1. Deploy Envoy: Configure an instance with an RBAC Deny rule that performs an exact match on a specific header (e.g., internal: true). 2. Baseline Test: Send a request containing the header internal: true. Observation: Envoy blocks this request (HTTP 403). 3. Exploit Test: Send a second request containing the same header twice: http GET /restricted-resource HTTP/1.1 Host: example.com internal: true internal: true Observation: Envoy allows the request, granting access to the resource.

6. Recommendations Fix Header Validation Logic: Modify the RBAC filter to validate each header value instance individually. Avoid relying on the concatenated string output of getAllOfHeaderAsString() for security-critical matching unless the matcher is explicitly designed to parse comma-separated lists.

Examine the DENY role to use a Regex style fix.

Credit: Dor Konis

1 / 2
Source: GitHub
First published (updated )
Severity
5.3
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

Summary

An off-by-one write in Envoy::JsonEscaper::escapeString() can corrupt std::string null-termination, causing undefined behavior and potentially leading to crashes or out-of-bounds reads when the resulting string is later treated as a C-string.

### Details

The bug is in the control-character escaping path in source/common/common/ jsonescapestring.h:67.

- The function pre-sizes result to the final length: std::string result(input.size() + requiredsize, '\\'); - For control characters (0x00..0x1f), it emits a JSON escape sequence of length 6: \u00XX. - It uses sprintf(&result[position + 1], "u%04x", ...), which writes 5 chars + a trailing NUL (\0) starting at result[position + 1]. - Then it does position += 6; and writes result[position] = '\\'; to overwrite the NUL. - If the control character occurs at the end of the output (e.g., the input ends with \x01), then after position += 6, position == result.size(), so result[position] is one past the end (off-by-one), violating std::string bounds/contract.

Concretely, the problematic lines are:

- source/common/common/jsonescapestring.h:69 (sprintf(...)) - source/common/common/jsonescapestring.h:72 (result[position] = '\\';)

Potentially reachable from request-driven paths that escape untrusted data, e.g. invalid header reporting:

- source/common/http/headerutility.cc:538 ~ source/common/http/ headerutility.cc:546 (escapes invalid header key for error text)

Even when this doesn’t immediately crash, it can break the std::string requirement that cstr()[size()] == '\0', which can later trigger UB (e.g., if passed to strlen, printf("%s"), or any C API that expects NUL termination). cpp //clang++ -std=c++20 -O0 -g -fsanitize=address -fno-omit-frame-pointer reprojsonescapeasan.cc -o reprojsonescapeasan ASANOPTIONS=abortonerror=1 ./reprojsonescapeasan #include <cstdint> #include <cstdio> #include <cstring> #include <string> #include <stringview>

static uint64t extraSpace(std::stringview input) { uint64t result = 0; for (unsigned char c : input) { switch (c) { case '\"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': result += 1; break; default: if (c == 0x00 || (c > 0x00 && c <= 0x1f)) { result += 5; } break; } } return result; }

static std::string escapeString(std::stringview input, uint64t requiredsize) { std::string result(input.size() + requiredsize, '\\'); uint64t position = 0;

for (unsigned char character : input) { switch (character) { case '\"': result[position + 1] = '\"'; position += 2; break; case '\\': position += 2; break; case '\b': result[position + 1] = 'b'; position += 2; break; case '\f': result[position + 1] = 'f'; position += 2; break; case '\n': result[position + 1] = 'n'; position += 2; break; case '\r': result[position + 1] = 'r'; position += 2; break; case '\t': result[position + 1] = 't'; position += 2; break; default: if (character == 0x00 || (character > 0x00 && character <= 0x1f)) { std::sprintf(&result[position + 1], "u%04x", staticcast<int>(character)); position += 6; // Off-by-one when this escape is the last output chunk: // position can become result.size(), so result[position] is out of bounds. result[position] = '\\'; } else { result[position++] = staticcast<char>(character); } break; } }

return result; }

int main() { std::string input(4096, 'A'); input.pushback('\x01'); // ends with a control char -> triggers the buggy path at the end

const uint64t required = extraSpace(input); std::string escaped = escapeString(input, required);

std::printf("escaped.size=%zu\n", escaped.size()); unsigned char terminator = staticcast<unsigned char>(escaped.cstr() [escaped.size()]); std::printf("escaped.cstr()[escaped.size()] = 0x%02x\n", terminator);

// If NUL termination is corrupted, this can read past the logical end. std::printf("strlen(escaped.cstr()) = %zu\n", std::strlen(escaped.cstr())); return 0; }

1 / 2
Source: GitHub
First published (updated )
Severity
5.9
Use After Free
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

Note: This vulnerability was originally reported to the Google OSS VRP (Issue ID: 477542544). The Google Security Team requested that I coordinate directly with the Envoy maintainers for triage and remediation. I am submitting this report here to facilitate that process.

Technical Details I have identified a logic vulnerability in Envoy's HTTP connection manager (FilterManager) that allows for Zombie Stream Filter Execution. This issue creates a "Use-After-Free" (UAF) or state-corruption window where filter callbacks are invoked on an HTTP stream that has already been logically reset and cleaned up.

Mechanism: The vulnerability resides in source/common/http/filtermanager.cc within the FilterManager::decodeData method.

When an HTTP/2 stream encounters a reset condition (e.g., StreamIdleTimeout, OverloadManager limits, or a local reset triggered by a filter), Envoy calls onResetStream. This method: 1. Sets the internal state state.sawdownstreamreset = true. 2. Invokes onDestroy() on all filters in the chain (allowing them to release resources/pointers). 3. Schedules the ActiveStream object for deferred deletion (cleanup happens later in the event loop).

The Flaw: The ActiveStream object remains valid in memory during the deferred deletion window. If a DATA frame arrives on this stream immediately after the reset (e.g., in the same packet processing cycle), the HTTP/2 codec invokes ActiveStream::decodeData, which cascades to FilterManager::decodeData.

FilterManager::decodeData fails to check the sawdownstreamreset flag. It iterates over the decoderfilters list and invokes decodeData() on filters that have already received onDestroy().

Root Cause Code Location: File: source/common/http/filtermanager.cc Function: FilterManager::decodeData

cpp void FilterManager::decodeData(...) { if (stopDecoderFilterChain()) { return; }

// Vulnerability: Missing check for state.sawdownstreamreset // Execution proceeds into the loop even if the stream is logically dead.

auto trailersaddedentry = decoderfilters.end(); for (; entry != decoderfilters.end(); entry++) { // ... calls (entry)->handle->decodeData(data) on destroyed filters ... } }

Suggested Fix: Add an explicit state check at the beginning of FilterManager::decodeData.

cpp // Prevent execution on streams that have been reset but not yet destroyed. if (state.sawdownstreamreset) { return; }

---

Impact Analysis

Who can exploit this: Any remote attacker capable of establishing an HTTP/2 or HTTP/3 connection. No privileges/authentication required.

Impact & Gain: 1. Memory Corruption & Potential Remote Code Execution: While the immediate symptom is a crash (DoS), the underlying primitive is a Use-After-Free (CWE-416). Mechanism: When onDestroy() is called on filters (e.g., Lua, Wasm, or complex native filters), they release internal structures and invalidate pointers. Exploitation: By forcing decodeData() to execute on these now-freed objects, an attacker triggers undefined behavior. In a heap-groomed environment, an attacker could potentially replace the freed filter object with a malicious payload before the "Zombie" decodeData call occurs. This would allow for vtable hijacking or arbitrary write-what-where primitives, leading to Remote Code Execution (RCE). Risk Amplification: This is particularly dangerous for Envoy deployments using memory-unsafe extensions or third-party filters (C++ extensions), where onDestroy logic is relied upon for safety.

2. Security Control Bypass: The vulnerability defeats Envoy's "Fail-Closed" security architecture. Scenario: If a stream is reset due to a security violation (e.g., StreamIdleTimeout, OverloadManager rejection, or WAF triggering), this vulnerability allows the attacker to bypass the termination. Result: The attacker can force the processing of "Data" frames on a connection that the security policy explicitly attempted to close, allowing malicious payloads to reach deeper into the filter chain or backend services despite the rejection.

---

Proof of Concept (Unit Test)

Description: The attached C++ unit test (zombiestreampoctest.cc) deterministically reproduces the vulnerability. It creates a stream, manually triggers a reset (simulating an Overload), and then immediately injects a DATA frame. The test asserts that the filter's decodeData callback is invoked on the reset stream.

cpp #include "test/common/http/connmanagerimpltestbase.h" #include "gmock/gmock.h" #include "gtest/gtest.h"

using testing::; using testing::Invoke; using testing::NiceMock; using testing::Return;

namespace Envoy { namespace Http {

/ Proof of Concept for "Zombie Stream Filter Execution" (HTTP/2 Reset Re-entrancy) Logic flow: 1. Open a stream with HEADERS. 2. Force a stream reset (simulating an Overload or Timeout). 3. Immediately inject DATA into the stream. 4. ASSERT that the filter's decodeData is called despite the stream being reset. / class ZombieStreamPocTest : public HttpConnectionManagerImplTest { };

TESTF(ZombieStreamPocTest, ReproducedZombieFilterExecution) { setup(SetupOpts().setTracing(false));

// 1. Setup a mock filter std::sharedptr<MockStreamDecoderFilter> filter(new NiceMock<MockStreamDecoderFilter>()); // Vuln confirmation: // We expect decodeData to be called on this filter even though the stream is reset. // In a secure/patched implementation, this EXPECTCALL should fail (Times(0)). EXPECTCALL(filter, decodeData(, )) .Times(1) .WillOnce(Invoke(& -> FilterDataStatus { ENVOYLOGMISC(error, "!!! VULNERABILITY REPRODUCED: decodeData called on a reset stream !!!"); return FilterDataStatus::Continue; }));

EXPECTCALL(filter, decodeHeaders(, false)) .WillOnce(Return(FilterHeadersStatus::StopIteration));

// Register the filter EXPECTCALL(filterfactory, createFilterChain()) .WillOnce(Invoke(& -> bool { auto factory = createDecoderFilterFactoryCb(filter); callbacks.setFilterConfigName("vulnerablefilter"); factory(callbacks); return true; }));

// 2. Start the stream EXPECTCALL(codec, dispatch()) .WillOnce(Invoke(& -> Http::Status { decoder = &connmanager->newStream(responseencoder); RequestHeaderMapPtr headers{new TestRequestHeaderMapImpl{ {":authority", "host"}, {":path", "/"}, {":method", "POST"}}}; decoder->decodeHeaders(std::move(headers), false); return Http::okStatus(); }));

// Dispatch headers Buffer::OwnedImpl headerbuffer("headers"); connmanager->onData(headerbuffer, false);

// 3. Trigger a Reset on the ActiveStream // This simulates Envoy terminating the stream due to an external event (Overload, Timeout). auto activestream = dynamiccast<ConnectionManagerImpl::ActiveStream>(decoder); // This sets state.sawdownstreamreset = true and triggers filter->onDestroy() activestream->onResetStream(StreamResetReason::LocalReset, "simulatedoverload");

// 4. Attack: Send DATA to the "Zombie" stream // The ActiveStream object is still alive in the deferred delete list. Buffer::OwnedImpl maliciouspayload("attackerdata"); // This call reaches the filter because FilterManager::decodeData misses the check! activestream->decodeData(maliciouspayload, false); }

} // namespace Http } // namespace Envoy

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
Use After Free
AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary

At the rate limit filter, if we enabled the response phase limit with applyonstreamdone in the rate limit configuration and the response phase limit request fails directly, it may crash Envoy.

Details

When both the request phase limit and response phase limit are enabled, the safe gRPC client instance will be re-used for both the request phase request and response phase request.

But after the request phase request is done, the inner state of the request phase limit request in gRPC client is not cleaned up. When we send the second limit request at response phase, and the second limit request fails directly, we may access the previous request's inner state and result in crash.

PoC

This need to mock the network failure. But we have reproduced by unit test locally.

Impact

This only happens when both the request phase limit and response phase limit are enabled in the rate limit filter, and requires the request to rate limit service fails directly (For example, if from Envoy's perspective, no healthy endpoint for rate limit service may result the request fails directly). That's say, not easy to trigger this.

To workaround

This could be worked around by splitting the rate limit filter. That is, if there is a rate limit filter that contains normal rate limit configuration (request phase limit, without applyonstreamdone) and also rate limit configuration with applyonstreamdone (response phase limit). Splitting them into two rate limit filters and ensure one filter only contains normal rate limit configuration (without applyonstreamdone), and one only contains rate limit configuration with applyonstreamdone could avoid this problem.

Credit

Mandar Jog (mandarjog@gmail.com)

1 / 2
Source: GitHub
First published (updated )
Severity
5.3
AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N

Summary

Forwarding of early CONNECT data in TCP proxy mode.

Details

Per RFC 7231-4.3.6 the sender of CONNECT (and all inbound proxies) switch to tunnel mode only after receiving 2xx response. However in TCP proxy mode, Envoy accepts client data before it has issued a 2xx response and eagerly proxies it to an established TCP connection. This creates possibility of a de-synchronized tunnel state if a proxy upstream from Envoy responds with a status other an 2xx.

The RFC does not specify the behavior in case an early CONNECT data is received and early CONNECT data is common as a latency reduction mechanism. To prevent disruption to existing deployments Envoy will by default allow early CONNECT data. Setting the envoy.reloadablefeatures.rejectearlyconnectdata runtime flag to true will cause CONNECT requests that send data before 2xx response to be rejected. This options should be enabled if there are intermediaries upstream from Envoy that may reject establishment of a CONNECT tunnel.

Impact

De-synchronization of CONNECT tunnel state if a forwarding proxy upstream from Envoy responds with a non 2xx status.

Attack vector(s) Sending data for a CONNECT request before receiving 2xx response.

Patches Users should upgrade to v1.36.3, v1.35.7, v1.34.11 or v1.33.13

Credits

chasingimpact (Patrick)

1 / 2
Source: GitHub
First published (updated )
Severity
7.1
AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:L/A:N

Summary Envoy’s mTLS certificate matcher for matchtypedsubjectaltnames may incorrectly treat certificates containing an embedded null byte (\0) inside an OTHERNAME SAN value as valid matches.

Details This occurs when the SAN is encoded as a BMPSTRING or UNIVERSALSTRING, and its UTF-8 conversion result is truncated at the first null byte during string assignment. As a result, "victim\0evil" may match an exact: "victim" rule and be accepted by Envoy.

PoC

Create a CA and a server certificate signed by that CA. Create two client certificates signed by the same CA: clientevil with OTHERNAME BMPSTRING = "evil" clientnull with OTHERNAME BMPSTRING = "victim\0evil" Configure Envoy with requireclientcertificate: true and a matchtypedsubjectaltnames entry for the OTHERNAME OID with matcher.exact: "victim". Connect without a client cert → connection rejected. Connect with clientevil → connection rejected. Connect with clientnull → connection accepted (but shouldn't!).

Impact An attacker who can obtain a trusted client certificate with a null byte embedded in an OTHERNAME SAN can exploit this vulnerability. The practical impact is unauthorized impersonation of the matched identity, enabling access to services or APIs protected by that exact OTHERNAME check.

Credit markevich.nikita1@gmail.com

1 / 2
Source: GitHub
First published (updated )
Severity
6.5
Null Pointer Dereference
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

Summary Envoy crashes when JWT authentication is configured with the remote JWKS fetching, allowmissingorfailed is enabled, multiple JWT tokens are present in the request headers and the JWKS fetch fails.

Details This is caused by a re-entry bug in the JwksFetcherImpl. When the first token's JWKS fetch fails, onJwksError() callback triggers processing of the second token, which calls fetch() again on the same fetcher object.

The original callback's reset() then clears the second fetch's state (receiver and request) which causes a crash when the async HTTP response arrives.

PoC allowmissingorfailed or allowmissing is enabled The client send 2 Authorization headers the remote JWKS fetching failed There will be crash

Impact DoS and Crash

Mitigation Disable the allowmissingorfailed or allowmissing

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203