MITIGATION · m-cross-client-isolation
Cross-client isolation — request-scope tenant boundaries in shared MCP server deployments
A shared MCP server that accepts connections from multiple clients is a concentration point where one client's session state, credentials, and resource budget are physically co-located with every other client's. Without enforced isolation, a malicious or compromised client can read another session's cached credentials, consume shared resources to the point of denying service to other clients, or exploit aggregate server permissions that exceed its own declared scope. Cross-client isolation is the set of structural controls that close those paths: per-session state scoping, per-client permission evaluation, and per-client resource quotas enforced at the server layer.
At a glance
TL;DR
- A shared MCP server holds session state for every connected client in the same memory space. Without explicit isolation, one client can read another's cached credentials or tool-call history through a state-management gap.
- Per-client permission scoping means every tool call is evaluated against the calling session's declared permission set, not the server's aggregate permissions. The server's combined scope is never the evaluation context for an individual client.
- Session state, including tokens and cached credentials, must be explicitly cleared on session termination. Relying on garbage-collector timing for secret erasure is not sufficient.
- Resource quotas are enforced per client so that one session exhausting its compute or external-API call budget cannot degrade service for other clients sharing the same server.
How it behaves
What it is
A shared MCP server runs a single process that handles tool calls from multiple clients simultaneously. That architecture concentrates state: session tokens, cached credentials, tool-call history, and in-progress context for every connected client exist in the same memory space. Isolation failure at any point in that shared space allows one client to observe or interfere with another.
The threat model has three distinct failure paths. First, a client reads another client's session artifacts, such as cached credentials or tool-call results, through a state-management bug or a missing scope check. Second, a client invokes tools using the server's aggregate permission set rather than its own narrower declared scope, gaining access it was never granted. Third, a client exhausts shared compute, memory, or external-API call budgets, denying service to all other clients on the same server.
Cross-client isolation addresses all three with matching structural controls:
- Session-scope state isolation: all per-client state (session tokens, cached credentials, tool-call history, context) is bound to a session identifier at creation and explicitly destroyed on session termination. No state persists beyond session lifetime, and no session identifier grants access to another session's records.
- Per-client permission scoping: each client's tool calls are evaluated against the permission set declared at session establishment. The server's aggregate permission set is never the evaluation scope for an individual client's call.
- Per-client resource quotas: compute, memory, and external-API call budgets are enforced per client so that one session consuming its full allocation does not reduce the capacity available to other sessions.
Detection signals
- Cross-session state access attempts logged per server instance. Each occurrence is a T42 signal; the expected rate is zero.
- Per-client permission denial rate. A sustained rise for a specific session identity indicates the client is probing for authority beyond its declared scope.
Threats it covers
-
WHY IT HELPS Cross-client interference in a shared MCP server depends on access to another session's state, cached credentials, or shared memory. Per-session state scoping, per-request context isolation, and session-key separation structurally remove those access paths, so there is no session artifact for an interfering client to reach.
-
WHY IT HELPS Network exposure of the MCP server is a precondition for T43; network exposure combined with insufficient isolation is what makes it exploitable. Per-client network policy, implemented as mutual TLS with per-client certificates and per-client egress rules, limits the network-level blast radius of any single client's access being abused by another.
-
WHY IT HELPS Insufficient isolation of MCP server permissions is the named threat. Per-client permission scoping, where each client's tool calls are evaluated against that client's declared permission set rather than the server's aggregate permission set, is the direct structural mitigation.
Principle coverage
Defence-in-Depth stage: Prevent — and it advances:
- Microsegmentation Cross-client isolation is microsegmentation applied to the MCP server layer: each client session is confined to its own state partition, permission set, and resource budget, so a misbehaving or compromised session cannot reach the state or consume the allocation of any adjacent session.
- Containment (blast radius) If a client session is compromised, cross-client isolation bounds the blast radius to that session's own state and declared permissions. The compromised session cannot read credentials from or exhaust the quota of any other session sharing the same server.
- Sandboxing & Isolation Cross-client isolation sandboxes the session boundary in shared MCP deployments the same way a container sandbox isolates the execution layer: the boundary is structural and enforced at the session and permission-evaluation layer, not by the agent's own runtime judgment.
- Least Common Mechanism Least Common Mechanism limits how much shared infrastructure is available across principals. Cross-client isolation applies that principle to the MCP server layer: each session operates on private state and a private permission scope rather than shared server-ambient context, reducing the coupling between clients at the session layer.
Design & governance principles (open design, economy of mechanism, accountability, …) are architectural, not advanced by a single placed control.
Implementation options
Five implementation options covering different layers of the isolation stack. Application-layer session management (MCP spec Mcp-Session-Id) is the baseline for all deployments. OS-level and VM-level options add depth for higher-assurance deployments.
MCP Mcp-Session-Id session management The MCP Streamable HTTP transport assigns a cryptographically secure session ID at initialization and requires clients to include it in every subsequent request via the Mcp-Session-Id header. The spec requires secure, non-deterministic session IDs and recommends binding them to user-specific information.
Why choose it: The universal baseline: every MCP server using the Streamable HTTP transport can implement this with no additional infrastructure. The MCP Security Best Practices document explicitly states that servers MUST use secure, non-deterministic session IDs and SHOULD bind them to user identity so that a guessed session ID cannot be used to access another client's session.
More details:
gVisor (runsc) gVisor interposes a user-space kernel (the Sentry) between the application and the host OS. Each client session runs in its own sandbox with its own Sentry instance, so shared process state, shared file descriptors, and shared IPC namespaces do not exist across client boundaries.
Why choose it: For deployments where clients have genuinely different trust levels and application-layer session management is not a sufficient boundary, such as MCP servers that execute untrusted tool code on behalf of clients. A compromised client session cannot craft arbitrary host syscalls that would affect another session's Sentry.
More details:
Kubernetes namespace-per-tenant Each client or client group is assigned its own Kubernetes namespace. RBAC Roles and RoleBindings are namespace-scoped, so a client's service account has no access to API resources in other namespaces. NetworkPolicy rules restrict pod-to-pod traffic.
Why choose it: For multi-tenant MCP deployments where each client maps to an organisational tenant and control-plane isolation (API resource separation) is required in addition to data-plane isolation (network). Combine with a ValidatingAdmissionPolicy that enforces required isolation labels at namespace creation time.
More details:
Cloudflare Durable Objects Assign each MCP client session its own Durable Object instance, keyed by session ID or client identity. Cloudflare guarantees each Durable Object has one active instance at any particular time with its own separate memory, so one session's state cannot reach another's.
Why choose it: For MCP servers deployed on Cloudflare Workers where session isolation is required with no infrastructure to operate. The per-instance memory guarantee holds as long as instance variables are used rather than global variables. The Cloudflare docs explicitly warn that global variables are shared across instances of the same class.
More details:
Per-connection subprocess (stdio transport) For each incoming MCP client connection, spawn a fresh OS process via the stdio transport that handles exactly one client for the lifetime of that session. The process starts with a clean address space, no shared heap, and no shared file descriptors beyond stdio.
Why choose it: The most structurally sound option when no platform isolation primitive is available. OS process isolation is the boundary: a compromised session cannot read another session's in-memory state through a shared heap or global variables. Dev effort is low when the MCP server already supports stdio.
More details:
Trade-offs
- Application-layer session management (Mcp-Session-Id) adds no measurable latency or cost: it is a map lookup and a header check.
- gVisor per-session sandboxing adds container startup overhead and increases memory footprint. Not all managed Kubernetes distributions support loading the runsc runtime handler.
- Kubernetes namespace-per-tenant multiplies API objects linearly with client count. At hundreds of tenants, control-plane etcd size and API server latency become operational concerns.
- The per-subprocess pattern scales memory linearly with concurrent sessions and adds a fork/exec cost per new connection (typically 20-100 ms). For long-lived sessions this cost is negligible; for short-lived high-frequency connections it can dominate.
When NOT to use
- Skip OS-level isolation (gVisor, subprocess) for single-tenant MCP servers where all clients share the same trust level and organisational boundary. The process-launch overhead is real cost for zero threat reduction.
- Do not apply Kubernetes namespace-per-tenant to deployments with hundreds of short-lived ephemeral clients. The namespace lifecycle management overhead exceeds the isolation value at that scale.
- Do not rely on application-layer session scoping alone when clients execute untrusted code or have filesystem or subprocess access inside the MCP server. Use gVisor or the per-subprocess pattern for that tier.
Limitations
- Application-layer session isolation does not prevent side-channel attacks (timing, cache-line, speculative execution) that exploit shared CPU or memory at the hardware level. Physical or VM-level isolation per client is required for highest-assurance deployments.
- gVisor reduces the syscall attack surface but does not eliminate shared-hardware side-channel risks.
- The MCP specification session management section covers Streamable HTTP transport only. The stdio transport has no Mcp-Session-Id mechanism; isolation must be enforced entirely by the process model.
- Per-client permission sets must be provisioned before session establishment. Adding a tool permission to an active session requires session re-establishment.
Maturity tier reasoning
- Tier 2 fits because every primitive used here, MCP Mcp-Session-Id session binding, gVisor runsc, Kubernetes namespace RBAC, Cloudflare Durable Objects, and OS subprocess isolation, is production-available and documented by its maintainer.
- What keeps the agentic MCP application at Tier 2 is the absence of a standardised multi-tenant session model in the MCP specification. The spec defines per-session IDs and security warnings but leaves multi-client isolation as an integration-time concern for each deployment.
- Advancement toward Tier 1 is expected as MCP reference server implementations add explicit per-client isolation APIs.
Last verified against upstream docs: 2026-05-30.