Envoy is a high-performance edge/middle/service proxy. External authentication can be bypassed by downstream connections. Downstream clients can force invalid gRPC requests to be sent to extauthz, circumventing extauthz checks when failuremodeallow is set to true. This issue has been addressed in released 1.29.1, 1.28.1, 1.27.3, and 1.26.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Pomerium is an open source identity-aware access proxy. Envoy, which Pomerium is based on, can abnormally terminate if an H/2 GOAWAY and SETTINGS frame are received in the same IO event. This can lead to a DoS in the presence of untrusted upstream servers. 0.15.1 contains an upgraded envoy binary with this vulnerability patched. If only trusted upstreams are configured, there is not substantial risk of this condition being triggered.
Pomerium is an open source identity-aware access proxy. Envoy, which Pomerium is based on, contains two authorization related vulnerabilities CVE-2021-32777 and CVE-2021-32779. This may lead to incorrect routing or authorization policy decisions. With specially crafted requests, incorrect authorization or routing decisions may be made by Pomerium. Pomerium v0.14.8 and v0.15.1 contain an upgraded envoy binary with these vulnerabilities patched. This issue can only be triggered when using path prefix based policy. Removing any such policies should provide mitigation.
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
Envoy is a high-performance edge/middle/service proxy. When PPv2 is enabled both on a listener and subsequent cluster, the Envoy instance will segfault when attempting to craft the upstream PPv2 header. This occurs when the downstream request has a command type of LOCAL and does not have the protocol block. This issue has been addressed in releases 1.29.1, 1.28.1, 1.27.3, and 1.26.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Envoy is a high-performance edge/middle/service proxy. Envoy crashes in Proxy protocol when using an address type that isn’t supported by the OS. Envoy is susceptible to crashing on a host with IPv6 disabled and a listener config with proxy protocol enabled when it receives a request where the client presents its IPv6 address. It is valid for a client to present its IPv6 address to a target server even though the whole chain is connected via IPv4. This issue has been addressed in released 1.29.1, 1.28.1, 1.27.3, and 1.26.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Envoy is a high-performance edge/middle/service proxy. Envoy will crash when certain timeouts happen within the same interval. The crash occurs when the following are true: 1. hedgeonpertrytimeout is enabled, 2. pertryidletimeout is enabled (it can only be done in configuration), 3. per-try-timeout is enabled, either through headers or configuration and its value is equal, or within the backoff interval of the pertryidletimeout. This issue has been addressed in released 1.29.1, 1.28.1, 1.27.3, and 1.26.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Envoy is a cloud-native high-performance edge/middle/service proxy. Envoy will crash when the http async client is handling sendLocalReply under some circumstance, e.g., websocket upgrade, and requests mirroring. The http async client will crash during the sendLocalReply() in http async client, one reason is http async client is duplicating the status code, another one is the destroy of router is called at the destructor of the async stream, while the stream is deferred deleted at first. There will be problems that the stream decoder is destroyed but its reference is called in router.onDestroy(), causing segment fault. This will impact extauthz if the upgrade and connection header are allowed, and request mirrorring. This issue has been addressed in versions 1.31.2, 1.30.6, 1.29.9, and 1.28.7. Users are advised to upgrade. There are no known workarounds for this vulnerability.
Summary Envoy's extproc HTTP filter is at risk of crashing if a local reply is sent to the external server due to the filter's life time issue. A known situation is the fail of a websocket handshake will trigger a local reply leading to the crash of Envoy.
PoC If both websocket and extproc are enabled, a failed handshake will trigger a local reply, thus extproc will crash.
Mitigation 1. Disable websocket traffic 2. Change the websocket response from backend to always return 101 Switch protocol based on RFC. 3. Apply the patch and the extproc filter will not send the local reply that is generated by Envoy to the extproc server for processing. 4. Apply the patch that the router will cancel the upstream requests when sending a local reply.
Impact Denial of service
Reporter Vasilios Syrakis Fernando Cainelli
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.
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)
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
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.
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.
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.
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.
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.
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.
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.
Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.37.0 until 1.37.5 and 1.38.3, when the %REQUESTEDSERVERNAME(X:Y)% is used in log format and host related options is specified, like HOSTFIRST, SNIFIRST, it's possible to crash Envoy when the specified host header is missing in the request headers. This vulnerability is fixed in 1.37.5 and 1.38.3.
HTTP/2 Rapid reset attack The HTTP/2 protocol allows clients to indicate to the server that a previous stream should be canceled by sending a RSTSTREAM frame. The protocol does not require the client and server to coordinate the cancellation in any way, the client may do it unilaterally. The client may also assume that the cancellation will take effect immediately when the server receives the RSTSTREAM frame, before any other data from that TCP connection is processed.
Abuse of this feature is called a Rapid Reset attack because it relies on the ability for an endpoint to send a RSTSTREAM frame immediately after sending a request frame, which makes the other endpoint start working and then rapidly resets the request. The request is canceled, but leaves the HTTP/2 connection open.
The HTTP/2 Rapid Reset attack built on this capability is simple: The client opens a large number of streams at once as in the standard HTTP/2 attack, but rather than waiting for a response to each request stream from the server or proxy, the client cancels each request immediately.
The ability to reset streams immediately allows each connection to have an indefinite number of requests in flight. By explicitly canceling the requests, the attacker never exceeds the limit on the number of concurrent open streams. The number of in-flight requests is no longer dependent on the round-trip time (RTT), but only on the available network bandwidth.
In a typical HTTP/2 server implementation, the server will still have to do significant amounts of work for canceled requests, such as allocating new stream data structures, parsing the query and doing header decompression, and mapping the URL to a resource. For reverse proxy implementations, the request may be proxied to the backend server before the RSTSTREAM frame is processed. The client on the other hand paid almost no costs for sending the requests. This creates an exploitable cost asymmetry between the server and the client.
Multiple software artifacts implementing HTTP/2 are affected. This advisory was originally ingested from the swift-nio-http2 repo advisory and their original conent follows.
swift-nio-http2 specific advisory swift-nio-http2 is vulnerable to a denial-of-service vulnerability in which a malicious client can create and then reset a large number of HTTP/2 streams in a short period of time. This causes swift-nio-http2 to commit to a large amount of expensive work which it then throws away, including creating entirely new Channels to serve the traffic. This can easily overwhelm an EventLoop and prevent it from making forward progress.
swift-nio-http2 1.28 contains a remediation for this issue that applies reset counter using a sliding window. This constrains the number of stream resets that may occur in a given window of time. Clients violating this limit will have their connections torn down. This allows clients to continue to cancel streams for legitimate reasons, while constraining malicious actors.
Pomerium is an open source identity-aware access proxy. Envoy, which Pomerium is based on, incorrectly handles resetting of HTTP/2 streams with excessive complexity. This can lead to high CPU utilization when a large number of streams are reset. This can result in a DoS condition. Pomerium versions 0.14.8 and 0.15.1 contain an upgraded envoy binary with this vulnerability patched.
Envoy is a cloud-native high-performance edge/middle/service proxy. Envoy’s HTTP/2 codec may leak a header map and bookkeeping structures upon receiving RSTSTREAM immediately followed by the GOAWAY frames from an upstream server. In nghttp2, cleanup of pending requests due to receipt of the GOAWAY frame skips de-allocation of the bookkeeping structure and pending compressed header. The error return [code path] is taken if connection is already marked for not sending more requests due to GOAWAY frame. The clean-up code is right after the return statement, causing memory leak. Denial of service through memory exhaustion. This vulnerability was patched in versions(s) 1.26.3, 1.25.8, 1.24.9, 1.23.11.
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
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.
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
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.
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
Envoy is an open source edge and service proxy designed for cloud-native applications. From 1.37.0 until 1.37.5 and 1.38.3, the HTTP OAuth2 filter (envoy.filters.http.oauth2) can leave an in-flight async token exchange attached to a downstream stream that has already been torn down. A late AsyncClient completion can still invoke OAuth2Filter methods that use StreamDecoderFilterCallbacks after that object’s lifetime has ended, causing undefined behavior, worker crashes (availability loss), and use-after-free / invalid-vptr failures under AddressSanitizer. This is a memory-safety / lifetime issue in the data plane, not a trivial config bug. Remote code execution is not claimed here; the primary demonstrated impact is DoS via crash and UB; any further impact would be deployment- and allocator-dependent. This vulnerability is fixed in 1.37.5 and 1.38.3.
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.