Security

Agent Router: MCP session seed still exposed in gateway pod args

Agent Router (formerly Envoy AI Gateway) - incomplete fix for GHSA-r86v-rw5r-2cpj: the extproc sidecar still receives the MCP session seed as a container argument (GHSA-3qgx-4x8m-wwhg)

PUBLISHED SEVERITY MEDIUMSTATUS PatchedGHSA-3qgx-4x8m-wwhg
Patched

Fixed in Agent Router 1.2.1 (2026-11-06): #2848 delivers the MCP session seeds to the extproc through the filter config Secret instead of container arguments, and the Helm chart now reads both seeds from Secrets. Track the fix at theagentrouter/agent-router#2848.

Product
Agent Router, formerly Envoy AI Gateway (Go module github.com/envoyproxy/ai-gateway, controller, extproc, Helm chart ai-gateway-helm) in theagentrouter/agent-router
Affected versions
Agent Router / Envoy AI Gateway 1.2.0 and earlier with an MCPRoute in use. Fixed in 1.2.1 (2026-11-06).
Severity
MEDIUM
Status
Patched
Weaknesses
  • CWE-214Invocation of Process Using Visible Sensitive Information
As filed on the advisory.
GitHub advisory
GHSA-3qgx-4x8m-wwhg
Published by the maintainer on 2026-11-06
CVE
Pending (requested from GitHub)
Published
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon (https://www.aeon.fun).

What users should do now

Upgrade to Agent Router 1.2.1 (released 2026-11-06). It includes #2848, which keeps the MCP session seeds out of Pod specs and process command lines.

  1. Upgrade the controller, the extproc image and the ai-gateway-helm chart to 1.2.1. Gateway pods that serve MCPRoutes roll once, because the extproc arguments change. Open MCP sessions survive as long as the seed stays the same.
  2. Treat the current seed as exposed. Before 1.2.1 it sat in every gateway Pod object, in etcd (Pod objects are not covered by Secret encryption at rest) and in any audit log that records Pod bodies. After upgrading, rotate it: set a new random controller.mcp.sessionEncryption.seed, keep the old one as controller.mcp.sessionEncryption.fallback.seed only until clients have reconnected, then remove the fallback.
  3. If you run the controller outside the chart, pass the seeds through the MCP_SESSION_ENCRYPTION_SEED and MCP_FALLBACK_SESSION_ENCRYPTION_SEED environment variables instead of the --mcpSessionEncryptionSeed and --mcpFallbackSessionEncryptionSeed flags. The flags still work and take precedence when set, but they put the seed on the process command line.
  4. Until you can upgrade, limit who can get, list or watch pods in gateway namespaces. That includes the built-in view ClusterRole and cluster-wide pod watchers such as monitoring, logging and policy agents. Leave the fallback seed unset unless you are in the middle of a rotation.

Summary

The MCP proxy in Agent Router encrypts each client's Mcp-Session-Id with a key derived from a seed. GHSA-r86v-rw5r-2cpj reported that this seed was passed as a literal argument in the pod spec, and was published on 2026-10-07 with 1.2.0 as the patched version. The 1.2.0 change (#2755) only touched the Helm chart: it stored the controller's seed in a Secret and handed it to the controller through an environment variable. It did not change how the controller passes the seed on to the extproc container that its mutating webhook injects into every Envoy gateway pod. That container still got -mcpSessionEncryptionSeed <seed> (and -mcpFallbackSessionEncryptionSeed <seed> when a fallback is set) as literal strings in container.Args. The chart also still passed the controller's fallback seed as a literal argument.

Affected versions

Agent Router, formerly Envoy AI Gateway (Go module github.com/envoyproxy/ai-gateway, Helm chart ai-gateway-helm), 1.2.0 and earlier, on any Gateway targeted by an MCPRoute. Fixed in 1.2.1 (2026-11-06). The fallback seed is only exposed when controller.mcp.sessionEncryption.fallback.seed is set, which the chart recommends during seed rotation and when upgrading from the old default seed. Reviewed on main at f4571d6 (2026-10-09); the same code is in v1.2.0.

Impact

Anyone who can read gateway pods can recover the MCP session-encryption seed, and the fallback seed if one is set. Pod read is a lower RBAC tier than Secret read, so this is the same gap GHSA-r86v-rw5r-2cpj describes. The seed could be read from:

  • The gateway Pod objects (kubectl get pod -o yaml, kubectl describe pod, or any get, list or watch on pods in the gateway namespace).
  • etcd, where Pod objects are not covered by Secret encryption at rest, and Kubernetes audit logs that record Pod create or update bodies.
  • The extproc process command line on the node, and the pprof cmdline endpoint, which is on by default and listens on 127.0.0.1 inside the pod.

With the seed, an attacker can decrypt any observed Mcp-Session-Id and read the route, subject and backend MCP session IDs inside it. Since GHSA-953h-535j-jg2v the gateway checks that a resumed session belongs to the caller's subject, but a seed holder can re-encrypt a captured victim's backend session IDs under their own subject and resume that session as themselves. On routes without authentication the subject is empty for everyone. A leaked fallback seed is as useful as the primary one, because the gateway accepts IDs that decrypt under it for as long as it is set. The attacker still needs pod read access, a valid identity on authenticated routes, and a captured session ID to take over a specific session; the seed alone does not reveal backend session IDs. This is why the issue is rated Medium. A working exploit is withheld.

Affected code

Permalinks at c7c4bf0, the parent of the fix commit.

Fix

  • #2848 (commit 6d63a4f, by the maintainer): the controller no longer adds the seeds to the extproc arguments. It writes them into the per-gateway filter config, which is already stored in a Secret and mounted into the extproc, and the extproc builds its session crypto from that config.
  • The controller now reads both seeds from the MCP_SESSION_ENCRYPTION_SEED and MCP_FALLBACK_SESSION_ENCRYPTION_SEED environment variables. The Helm chart stores the fallback seed in its own Secret and no longer passes either seed as an argument.
  • The seeds are also left out of the extproc config hash stored as a pod-template annotation, so it can no longer be used to test seed guesses offline.
  • Backported to the 1.2 branch as 309d90c and shipped in 1.2.1. Still present on main at d41f082 (2026-11-06).

Detection (for defenders)

  • Check whether your gateway pods carry the seed: look for -mcpSessionEncryptionSeed or -mcpFallbackSessionEncryptionSeed in the extproc container args. On 1.2.1 the extproc gets only -mcpAddr for MCP.
  • Check the controller Deployment for a literal --mcpFallbackSessionEncryptionSeed= argument.
  • Review which users and service accounts can read pods in gateway namespaces, and whether your audit logs keep Pod request bodies. If the seed was readable by anyone you do not trust with it, rotate it.

Timeline

  1. GHSA-r86v-rw5r-2cpj published with 1.2.0 as the patched version.
  2. Reported privately via GitHub PVR (GHSA-3qgx-4x8m-wwhg): the extproc part of GHSA-r86v-rw5r-2cpj was still present in 1.2.0 and on main, with a suggested fix.
  3. Maintainer accepts the report (Medium, CWE-214) and opens #2848. We asked for a patched version and a CVE request at publication.
  4. #2848 merged.
  5. We asked the maintainer to finish the advisory and request a CVE from GitHub.
  6. Agent Router 1.2.1 released with the fix; the maintainer publishes GHSA-3qgx-4x8m-wwhg. Public write-up.

Credit

Finder: Aaron Elijah Mars of Aeon. Tool: Aeon.

Fix in #2848 by nacx.

References