Enterprise teams use MCP gateways to control how AI agents reach tools, services, and company data. Agentgateway, an open source project hosted by the Agentic AI Foundation, routes MCP, Agent-to-Agent, LLM, and API traffic between clients and backend services. Its open code, tests, and advisories make it useful for studying enterprise gateway security in practice.
My previous security research has focused on how AI agents interact with the infrastructure around them. For this blog, I wanted to look more closely at agentgateway and ask a narrower question: what happens when a gateway's view of an operation differs from what the upstream receives? Protocol translation, request-body inspection, and session reuse each create a version of that problem.
While following those paths, I found it useful to think about three practical contracts. Tool arguments stay within their intended HTTP fields. A policy can tell whether it saw the complete request. The gateway preserves a stateful session's backend selection across requests. The way agentgateway now handles these cases shows how the contracts apply to stateful MCP and the stateless 2026-07-28 protocol.

Figure 1. Three MCP gateway contracts preserve HTTP field boundaries, inspection completeness, and backend binding.
The translation contract preserves HTTP field boundaries
Protocol translation lets an MCP client call an existing OpenAPI service. It converts client-controlled JSON into HTTP paths, query strings, and headers.
An earlier disclosure shows how this can go wrong during translation. Research by @spacewander tested Higress, agentgateway, LiteLLM, and Unla. The projects used different languages and HTTP stacks, but each allowed tool arguments to alter parts of the upstream request beyond their intended parameter values. The affected fields included paths, query strings, and headers.
Agentgateway v0.12.0 changed how it builds upstream requests. The fix ships percent-encoding for substituted path-parameter values, query keys, and query values. It accepts only headers declared in the OpenAPI schema and prevents tool arguments from replacing protected or existing headers. Agentgateway also published an advisory for CVE-2026-29791. Once the adapter constructs a different request, the HTTP client cannot recover the intended field boundaries. The gateway has to keep each argument in the field declared by the schema.
The inspection contract makes completeness explicit
Gateways also often inspect request bodies before forwarding them. Reading an unlimited body can consume memory and delay streaming, so many gateways set buffer limits. The difficult part is telling a security policy when that limit leaves part of the request unseen.
During a security review of agentgateway's request-time Common Expression Language (CEL) policies, I found a gap between the body a policy inspected and the body sent upstream. Before v1.4.0, an oversized body appeared in request.body as the first maxBufferSize bytes without a completeness signal. Agentgateway still forwarded the complete request body upstream.
A deny rule used string(request.body).contains("attacker-payload"). A small matching request was blocked, but placing the same value after a large JSON padding field moved it beyond the inspection boundary. The policy saw a harmless prefix, while the upstream parsed the complete valid JSON document.
For request-time expressions, agentgateway v1.4.0 makes body completeness explicit. request.body is available only when the complete body fits within maxBufferSize. If it does not, the expression fails to evaluate. request.bodyPrefix exposes the full body when it fits, or the first maxBufferSize bytes when it does not.
That evaluation failure does not make a body-dependent Deny policy fail closed. A failed Deny expression does not reject the request, so the documentation recommends Allow or Require when evaluation failure must block.
request.bodyPrefix never means that the policy saw the complete body. It works when a rule depends on the prefix itself, such as a fixed file signature or protocol preamble. Checks for a JSON field, nested object, or forbidden value anywhere in the body require the complete request.
The session contract preserves backend selection
Stateful MCP lets a client continue a server-side session across requests. In a 2025-11-25 deployment, the client sends Mcp-Session-Id after initialization. Before applying the current route's authorization policy, the gateway needs to confirm that the session belongs to the selected backend.
Before v1.4.0, agentgateway could reuse an MCP session without checking whether the current request selected the same backend. The current request supplied the MCP authorization policy, while the session supplied the existing upstream connection.
I reproduced the mismatch with two routes. /sensitive selected sensitive.example.com with deny-all-traffic. /permissive selected permissive.example.com with allow-all-traffic.
In agentgateway versions before v1.4.0, MCP authorization did not prevent session initialization on /sensitive. The client could then reuse that session ID on /permissive. Agentgateway applied allow-all-traffic from the permissive route while sending the tool call over the existing connection to sensitive.example.com.
The request used one route's policy and another route's connection:
MCP authorization policy = allow-all-traffic (/permissive)
upstream connection = sensitive.example.com (/sensitive)
I shared the reproduction with the agentgateway team. John Howard confirmed it, and we found that the issue affected stateful MCP configurations with multiple backends on different routes. Agentgateway published GHSA-mvgg-jvj2-4frq with a High rating and a CVSS score of 8.1.
Agentgateway v1.4.0 now stores the selected backend group's ResourceName as backend_id in each SessionEntry. Before resuming a session, it compares that value with the backend group selected for the current request and rejects a mismatch. The patch includes a cross-backend regression test.

sequenceDiagram
autonumber
participant C as MCP client
participant R as Agentgateway router
participant M as Session manager
participant S as sensitive.example.com C->>R: initialize on /sensitive
Note over R: Select sensitive backend group
R->>S: initialize
S-->>R: initialize succeeds
Note over R: Prepare Mcp-Session-Id: SID-A
R->>M: insert_session(sensitive, session, ttl)
Note over M: Store backend_id ResourceName(sensitive)
R-->>C: SID-AIn agentgateway, a session ID can recover an upstream connection. Agentgateway therefore checks its saved backend before using the authorization settings from the current request.
Stateless MCP changes the session contract
MCP 2026-07-28 removes the reusable protocol session. The protocol no longer uses the initialize handshake or Mcp-Session-Id. The protocol version, client identity, and client capabilities now travel with each request, so gateways do not need sticky routing or a shared store for MCP protocol sessions.
This change removes only the need to bind an MCP protocol session to a backend. Stateful MCP 2025-11-25 still needs the backend check described above when a gateway issues a session. MCP 2026-07-28 has no protocol session to bind. Neither version removes translation or body-inspection risks where those features are used. Authentication, rate limits, and application features can still keep their own state outside the MCP protocol.
Agentgateway v1.4.0 supports both versions. It checks the backend for stateful clients and handles MCP 2026-07-28 requests without protocol sessions. The protocol version on each request determines which path it follows.
Enterprise MCP gateway security beyond these cases
Together, these cases cover only part of what an enterprise MCP gateway protects. The same gateway authenticates callers, handles credentials, applies policy, routes traffic, and supports multiple protocol versions. Every new backend and protocol version creates more paths through those controls.
Working through these cases with the agentgateway team gave me a closer view of the project. I appreciated how the team documented the changes and made the patches, tests, and advisories public. That transparency matters for an enterprise gateway between AI agents and company systems.
Share
Author

Aonan Guan
Aonan Guan is a security researcher focused on AI and cloud security and leads Security at Wyze Labs.



