{"answers":{"affected":"2 open source packages ship an affected version, including github.com/envoyproxy/ai-gateway.","exploited":"There is no known exploitation of GHSA-953h-535j-jg2v in the wild and no public exploit code.","fix":"Upgrade github.com/envoyproxy/ai-gateway to 1.2.0-rc1 or later.","what":"GHSA-953h-535j-jg2v is an authentication bypass vulnerability in github.com/envoyproxy/ai-gateway, published on 19 Oct 2026. Any signed-in user can exploit it over the network, with no action from the victim."},"fix_prompt":"Check this codebase for GHSA-953h-535j-jg2v and fix it if it is affected.\n\nWhat it is: GHSA-953h-535j-jg2v is an authentication bypass vulnerability in github.com/envoyproxy/ai-gateway, published on 19 Oct 2026. Any signed-in user can exploit it over the network, with no action from the victim.\nExploitation: There is no known exploitation of GHSA-953h-535j-jg2v in the wild and no public exploit code.\n\nAffected packages and fixed versions:\n- github.com/envoyproxy/ai-gateway (Go): affected from 0.4.0-rc1; fixed in 1.2.0-rc1\n- github.com/envoyproxy/ai-gateway (Go): affected from 0.4.0-rc1; fixed in 1.2.0-rc1\n\nTask:\n1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.\n2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.\n3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.\n4. Run the tests and summarise what changed and why.\n5. If nothing in the project is affected, say so and change nothing.\n\nReference: https://insights.sbomify.com/GHSA-953h-535j-jg2v/ (Markdown: https://insights.sbomify.com/GHSA-953h-535j-jg2v/index.md)","id":"GHSA-953h-535j-jg2v","markdown":"https://insights.sbomify.com/GHSA-953h-535j-jg2v/index.md","name":"GHSA-953h-535j-jg2v","record":{"aliases":[],"analysis":{"component_type":"server_software","fix_type":"patch","impacts":["privilege_escalation","data_read"],"network_reachable":"yes","non_default_config":false,"product_category":"MCP proxy gateway","requires_auth":"low_privilege","summary":"Attackers can hijack MCP sessions by forging IDs due to missing subject verification and insecure default seeds, allowing unauthorized access to other users' data.","user_interaction":"not_required","vuln_class":"auth_bypass"},"analysis_generated_by":"qwen3.8-flash-next","assigner":null,"cpe":[],"cvss":{"score":null,"severity":null,"source":null,"vector":null,"version":null},"cwes":[],"description":"## Summary\n\nThe MCP proxy's client-facing session ID embeds the authenticated caller's\nsubject (JWT `sub` claim) specifically as an anti-hijacking discriminator —\nmatching the Model Context Protocol specification's documented session-hijacking\nguidance (https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#session-hijacking).\nHowever, the session-resume path never checks that discriminator against the\ncurrent caller's identity, so any client that obtains a session ID (its own or\nanother user's) can resume that session and act with it — including on\nroutes with per-user backend sessions. This is aggravated by the official\nHelm chart shipping a literal, publicly known default seed\n(`\"default-insecure-seed\"`) for the key that encrypts these session IDs.\n\n## Impact\n\nAn attacker who obtains (or, under the default seed, forges) another user's\n`Mcp-Session-Id` value can resume that user's MCP session against the backend\nMCP server(s) bound to the route — reading conversation/tool-call state and\ninvoking further JSON-RPC methods (e.g. `tools/call`, `resources/read`) in the\ncontext of that other user's already-initialized backend session. On a\nmulti-tenant AI Gateway deployment, this crosses the exact trust boundary the\nsubject-embedding was added to protect.\n\n## Location\n\n- `internal/mcpproxy/session.go` — `clientToGatewaySessionID.backendSessionIDs()`\n  (around line 707-765): parses `{routeName}@{subject}@{backends}` and returns\n  only `(perBackendSessionIDs, route, error)`. The comment at the subject-parsing\n  site reads: \"The subject ... is retained inside the encrypted session ID for\n  anti-hijacking purposes but is not needed during parsing.\" — the subject is\n  discarded, never returned, never compared.\n- `internal/mcpproxy/mcpproxy.go` — `sessionFromID(id, lastEvent)` (around line\n  282-323): resumes a session purely from the decrypted blob; it is never passed\n  the current request's authenticated subject, so there is nothing to compare\n  against even if `backendSessionIDs()` did return it.\n- `internal/mcpproxy/legacy.go` — `extractSubject(r)` (around line 1549-1562) is\n  called exactly once, only at session creation (`handleInitializeRequest` -\u003e\n  `newSession`, line ~307/484/491) to embed the subject when the session ID is\n  minted. All three session-resume call sites (`serveGET`/`servePOST`/`serverDELETE`\n  paths, lines ~133, 167, 216) call `sessionFromID` with no subject argument at all.\n- `internal/mcpproxy/mcpproxy.go` line 259 (`clientToGatewaySessionIDFromEntries`)\n  is where the subject is embedded at creation, confirming the intended design.\n- Aggravating factor: `manifests/charts/ai-gateway-helm/values.yaml` line 297\n  ships `seed: \"default-insecure-seed\"` as the out-of-the-box value for\n  `controller.mcp.sessionEncryption.seed`, which `templates/deployment.yaml`\n  passes straight to `--mcpSessionEncryptionSeed` (also literally defaulted to\n  `\"default-insecure-seed\"` in `cmd/controller/main.go` and\n  `cmd/extproc/mainlib/main.go` when the flag is omitted entirely). Session IDs\n  are `salt || nonce || ciphertext` (see `internal/mcpproxy/crypto.go`), so\n  knowing the seed and the (also-defaulted) PBKDF2 iteration count is sufficient\n  to derive the AES-GCM key and both decrypt observed session IDs and encrypt\n  new ones for an arbitrary chosen subject/backend-session combination.\n\n## Reproduction (code-level, not run against a live cluster)\n\n1. Deploy Envoy AI Gateway with an `MCPRoute` that has an OAuth/JWT\n   `SecurityPolicy` attached (so `internalapi.MCPSubjectHeader` is populated)\n   and at least one backend MCP server, using the Helm chart's default\n   `values.yaml` (`controller.mcp.sessionEncryption.seed` left at\n   `\"default-insecure-seed\"`).\n2. User A authenticates with a valid JWT (`sub: user-a`) and sends an\n   `initialize` JSON-RPC request to the route. The gateway creates backend\n   session(s) and returns `Mcp-Session-Id: \u003cencrypted-blob-A\u003e`, whose plaintext\n   is `{route}@user-a@{backend}:{base64(sessionID)}:{capHex}`.\n3. Attacker (any other authenticated user, or — since the seed is public and\n   default — even without ever having a legitimate session at all) constructs\n   `{route}@user-a@{backend}:{base64(\u003cany-or-known-backend-session-id\u003e)}:fff`,\n   derives the AES-GCM key via PBKDF2(sha256, \"default-insecure-seed\",\n   salt, 100000, 32) for a salt of their choosing, and encrypts it themselves\n   to produce a session ID that decrypts to the same structure `sessionFromID`\n   expects.\n4. Attacker sends a subsequent JSON-RPC request (e.g. `tools/call`) to the same\n   route with header `Mcp-Session-Id: \u003cforged-or-captured-blob-A\u003e`. The gateway\n   decrypts it, extracts `perBackendSessionIDs` for `backend`, and forwards the\n   attacker's call using that backend session — with no comparison to the\n   attacker's own JWT subject at any point in `sessionFromID` /\n   `backendSessionIDs()`.\n\n## Suggested fix\n\n- In `sessionFromID`, thread the current request's `extractSubject(r)` value\n  through to `backendSessionIDs()` (or a wrapping call) and reject resumption\n  (401/403) when the decrypted subject does not match the current caller's\n  subject — restoring the anti-hijacking check the embedding was built for.\n- Independently, change the Helm chart's default\n  `controller.mcp.sessionEncryption.seed` to be randomly generated per\n  install (e.g. via a Helm `lookup`/`randAlphaNum` in a pre-install hook, or a\n  required value with no default), rather than shipping a literal, fixed\n  string. At minimum, fail startup (rather than just logging) when the seed\n  equals the documented insecure default in a non-dev/insecure-allowed mode.\n\n## Detected by\n\nAeon vuln-scanner — agentic dataflow review (`internal/mcpproxy` entrypoint,\nEnvoy AI Gateway data-plane MCP proxy), followed by manual adversarial\nverification against the exact HEAD commit of `main`\n(`472da7db7984f769c9a77671d12c0354e75fc3ba`, confirmed to match\n`repos/theagentrouter/agent-router/commits/main` at time of report).\nDependency-CVE findings from this scan (osv-scanner, `go.mod`/`package-lock.json`)\nare not included here — they are all already covered by open Dependabot PRs\n(#2555, #2643, #2672, #2497, #2615) and are omitted to avoid duplicate filings.","ecosystems":["Go"],"exploits":{"exploitdb":null,"first_seen":null,"github_poc":null,"max_poc_stars":null,"metasploit":null,"nuclei":null,"refs":[],"tier":null},"has_fix":true,"headline":"The MCP proxy's client-facing session ID embeds the authenticated caller's subject (JWT `sub` claim) specifically as an anti-hija","id":"GHSA-953h-535j-jg2v","indexable":true,"kev":null,"kind":"advisory","links":{"ecosystem":"Go","product":null,"products":[],"type":"auth_bypass","year":"2026"},"n_packages":2,"n_references":null,"packages":[{"ecosystem":"Go","fixed":["1.2.0-rc1"],"introduced":["0.4.0-rc1"],"last_affected":[],"package":"github.com/envoyproxy/ai-gateway","purl":null,"source":"GHSA-953h-535j-jg2v"},{"ecosystem":"Go","fixed":["1.2.0-rc1"],"introduced":["0.4.0-rc1"],"last_affected":[],"package":"github.com/envoyproxy/ai-gateway","purl":"pkg:golang/github.com/envoyproxy/ai-gateway","source":"GHSA-953h-535j-jg2v"}],"products":null,"published":"2026-10-19","related":[],"sources":[{"class":"attribution","licence":"CC BY 4.0","name":"GitHub Advisory Database","prefix":"GHSA"}],"ssvc":{"automatable":null,"exploitation":null,"technical_impact":null},"state":null,"updated":null,"vendors":null},"summary":"Attackers can hijack MCP sessions by forging IDs due to missing subject verification and insecure default seeds, allowing unauthorized access to other users' data.","url":"https://insights.sbomify.com/GHSA-953h-535j-jg2v/"}