← Atlas · Mitigations Tier 2 · Real-composable

MITIGATION · m-session-isolation

Session-scoped memory isolation — preventing cross-session context bleed

An agent that serves multiple users stores conversation history, retrieved facts, and intermediate state in a memory layer. If that layer is not scoped to the originating session, one user's writes can reach another user's retrieval path. Session-scoped memory isolation prevents that by enforcing a hard boundary at the storage layer, so each session can only read and write its own state.

Last reviewed 2026-05-12 · Status: published · Evidence →

At a glance

MATURITY
Tier 2
Available off-the-shelf or as a documented pattern, but newer or less broadly proven. Expect integration work and some operational nuance.
PLACES ON
node
Restricted to node kinds: shared-memory
COVERAGE
1 threat
T1
TRADE-OFFS
LAT
low
COST
low
UX
low
DEV
medium
Latency · cost · UX friction · dev effort.
TL;DR
  • Every memory record must carry a session_id tag at write time. The storage layer, retrieval layer, and write layer each enforce the boundary independently; a gap in any one of the three allows cross-session reads.
  • Retrieval queries that omit the session_id parameter must return empty, not fall through to a shared namespace. Fail-empty is the safe default; fail-open to shared state is the common misconfiguration.
  • This control closes the OWASP T1 Shared Memory Poisoning scenario: a user's memory writes cannot reach another user's retrieval path when session scoping is enforced at all three layers.
  • Sibling control m-cross-client-isolation covers MCP multi-tenant server isolation. This page is scoped to per-user-session memory isolation in conversational and agent runtimes.

How it behaves

Agent reads from or writes to the memory store (vector, key-value, or relational)
Is the operation parameterised on a session_id that is bound to the current authenticated user session, and is that parameter enforced at the storage layer (not only in application code)?
Operation executes within the session boundary, no cross-session access possible
Isolation violation, reads or writes may span sessions; reject and alert
Application-layer-only enforcement is not sufficient: an untagged code path, a framework bypass, or a direct storage query can cross the boundary. The storage layer must enforce the scope independently.

What it is

A multi-user agent runtime maintains memory: it stores conversation turns, retrieved documents, and intermediate reasoning state so each interaction can build on what came before. When that memory lives in a shared store, and writes are not scoped to the session that produced them, the boundary between users collapses. A retrieval query issued on behalf of user A can return records written by user B. That is context bleed: the agent treats another user's data as its own context.

Session-scoped memory isolation prevents this by enforcing a tenant boundary at three independent layers:

  1. Storage layer: every memory record is tagged with a session_id (or tenant_id combined with session_id for multi-tenant systems). Pinecone namespaces, Weaviate tenants, and Postgres row-level security policies each enforce that tag as a structural partition, not a query-time filter that can be omitted.
  2. Retrieval layer: every query is parameterised on the session identifier. A query that omits the parameter returns empty rather than falling through to a shared namespace. Fail-empty is the safe default.
  3. Write layer: writes without a session identifier are rejected at the boundary. A write that attempts to span sessions is rejected.

The enforcement must exist at all three layers independently. Application-layer-only scoping, such as a query builder that appends a filter but does not enforce it at the storage engine, can be bypassed by a direct storage call, a framework bypass, or an unaudited code path. The storage layer must enforce the scope on its own.

This control addresses OWASP Agentic AI v1.1 §T1 Memory Poisoning, specifically the §Shared Memory Poisoning named scenario. Sibling control m-cross-client-isolation covers MCP multi-tenant server isolation; this page covers per-user-session memory isolation in conversational and agent runtimes.

Detection signals

  • Cross-namespace reads reaching unintended sessions. Any read operation that returns records outside the querying session's namespace indicates a missing or bypassed isolation boundary.
  • Memory writes without a session identifier tag. A write that omits the session-id is an untagged code path; accumulation of untagged records means the isolation boundary has gaps.

Threats it covers

  • T1 Memory Poisoning −1 severity step

    WHY IT HELPS Memory Poisoning includes a cross-session and cross-tenant variant: a user who can write to a shared memory store may place content that another session later retrieves as its own context. Session isolation closes that path by ensuring that memory written in one session is structurally unreachable from any other, regardless of the content's nature.

Principle coverage

Defence-in-Depth stage: Prevent — and it advances:

  • Attack Surface Minimization Session isolation removes the shared memory surface entirely: a session that has no structural path to another session's records cannot be used to attack those records, regardless of what the agent is prompted to retrieve.
  • Microsegmentation Session isolation is microsegmentation applied to agent memory: each session is confined to its own partition of the memory store, so a misbehaving or compromised session cannot reach the state of any adjacent session.
  • Containment (blast radius) If a session is compromised, session isolation bounds the blast radius to that session's own memory. The compromised session cannot read from or write into adjacent sessions, limiting what an attacker can observe or pollute.
  • Sandboxing & Isolation Session isolation sandboxes the memory layer the same way a container sandbox isolates the execution layer: the boundary is structural and enforced at the storage engine, not by the agent's own runtime judgment.
  • Memory & RAG Integrity Memory integrity requires that what an agent retrieves is what the correct principal wrote. Session isolation enforces that requirement at the namespace level: a retrieval path that is scoped to a single session cannot return records written by a different principal.
  • Data Minimization & Privacy Session isolation is data minimisation applied to the retrieval layer: each session can only access its own records, so the agent never retrieves data from other users' interactions that it has no legitimate reason to hold.
  • Least Common Mechanism Least Common Mechanism limits how much shared infrastructure is available across principals. Session isolation applies that principle to the memory store: each session operates on a private partition rather than a shared namespace, reducing the coupling between users at the storage layer.

Design & governance principles (open design, economy of mechanism, accountability, …) are architectural, not advanced by a single placed control.

Implementation options

Five verified implementation options covering managed API isolation, framework-level session scoping, vector-store namespace isolation, Redis-backed TTL-scoped memory, and a self-build explicit session store. Most production deployments compose two or three of these, typically a storage-layer option plus a framework-level option.

OpenAI Responses API Server-side conversation state scoped to a unique conversation_id. State is not accessible across conversation IDs, and the isolation boundary is enforced at the API layer.

Why choose it: Best when your agent stack already targets the OpenAI API and you want managed server-side memory without operating your own store. The application is responsible for mapping one conversation_id to one authenticated user session, never reuse a conversation_id across users. The predecessor Assistants API Threads model (now migrating to Responses API Conversations) followed the same per-thread isolation principle.

More details:

Anthropic Messages API Fully stateless per-call design: the server retains no conversation history between calls. Cross-session contamination at the API layer is structurally impossible because there is no shared server-side store.

Why choose it: Best when you want the strongest possible guarantee that the model provider holds no cross-session state. The isolation burden shifts entirely to the application: store each user's messages array in a session-scoped store (database row, cache key, or in-memory structure keyed on session_id) and never merge two users' arrays. This is the model for all Anthropic-native conversational agents; the stateless design means the API itself cannot be the contamination vector.

More details:

LlamaIndex ChatMemoryBuffer Scopes all chat history operations to a chat_store_key that acts as the session identifier. Supported backends include SimpleChatStore, RedisChatStore, PostgresChatStore, DynamoDBChatStore, and AzureChatStore.

Why choose it: Best when your agent stack is built on LlamaIndex and you want framework-managed session isolation without wiring a custom store. Set chat_store_key to a value derived from the authenticated user's session identifier, never use a constant or user-supplied value. The storage backend enforces the boundary: a RedisChatStore or PostgresChatStore key includes the session identifier in the key name, making cross-session reads structurally impossible without knowing the key. Pair with a backend that has server-side TTL support (Redis EXPIRE, Postgres row TTL) so sessions are cleaned up automatically on disconnect.

More details:

Pinecone namespaces Logical partitions within a Pinecone index. Each upsert and query call accepts a namespace parameter; queries are limited to a single namespace and cannot cross namespace boundaries without an explicit multi-namespace call.

Why choose it: Best when your agent uses a Pinecone index for long-term or retrieval-augmented memory and you want storage-layer isolation with no additional infrastructure. The namespace parameter must be set on every upsert and every query, an upsert without a namespace goes to the default namespace, which is shared; enforce a non-empty namespace at the application layer and reject any operation that omits it. For multi-tenant deployments where tenants must not share index resources at all, use separate indexes per tenant instead of namespaces within one index. For session-level isolation within a single tenant, namespaces are the correct primitive.

More details:

AWS Bedrock Agents Scopes all session attributes and conversation history to a sessionId. Requests sharing the same sessionId belong to the same session; sessions expire automatically after idleSessionTTLInSeconds.

Why choose it: Best when your agent is deployed on the Bedrock Agents platform and you want managed session scoping with automatic TTL-based cleanup. The sessionId must be generated by your application and bound to the authenticated user, never reuse a sessionId across users. The idleSessionTTLInSeconds parameter ensures sessions are automatically invalidated after inactivity, preventing stale session state from accumulating and being reused. Pair with AWS IAM session-level policies to ensure the sessionId cannot be forged by the client.

More details:

Trade-offs

  • Namespace and key-prefix isolation at the storage layer (Pinecone namespaces, Redis key prefixes, Bedrock sessionId) adds sub-millisecond overhead, the namespace filter is applied at the index layer, not in application code.
  • Framework-level session scoping (LlamaIndex chat_store_key) adds no latency; the session key is resolved before the storage call and is never a runtime lookup.
  • The primary development cost is not implementing the isolation primitive, it is auditing every read and write path in the agent to confirm the session identifier is always present and always derived from the authenticated session, never from a user-supplied parameter.
  • Retrofitting session isolation onto an existing shared store is the costly case: teams typically find two to five untagged code paths per 10,000 lines of agent infrastructure that must be corrected before isolation is trustworthy.
  • Stateless API isolation (Anthropic Messages API) eliminates the server-side isolation problem entirely but shifts the burden to the application's session store, that store then becomes the isolation boundary that must be audited.

When NOT to use

  • Do not use session isolation when agents need legitimate cross-session knowledge, a knowledge-base agent designed to surface shared answers from all users' interactions will be silently broken by per-session isolation.
  • Do not use session isolation as the sole control for a multi-tenancy compliance requirement: it scopes memory but does not enforce the wider identity, billing, audit-log, and network separation that full multi-tenancy requires.
  • Do not apply session isolation to single-user deployments where only one session ever exists, the single-tenant threat model does not include cross-session contamination and the wiring cost is not justified.

Limitations

  • Session isolation does not stop poisoning within a session, a user who injects malicious content into their own session memory can still steer their own agent's behaviour. Pair with m-mem-validation for content-level write-time controls.
  • Application-layer-only enforcement (filtering in a query builder without a storage-layer constraint) is defeatable by direct storage access, framework bypasses, or unaudited code paths. The storage layer must enforce the boundary independently.
  • Session cleanup on disconnect is not automatic in most self-build patterns: unless session scoping is paired with an explicit TTL (Redis EXPIRE, Bedrock idleSessionTTLInSeconds) or a delete-on-disconnect handler, stale session state accumulates indefinitely.
  • Cross-session aggregate queries, for example, analytics over all sessions, are a legitimate operational need that breaks the isolation model. Implement those via a separate read replica or aggregate pipeline that is not exposed to the agent runtime.

Maturity tier reasoning

  • Tier 2 fits because multi-tenant data isolation using namespace and session-key primitives is Tier 1 mature in the underlying storage layers (Pinecone, Redis, Postgres RLS, Bedrock); applying those primitives to agent memory is operational composition, not novel engineering.
  • What keeps this out of Tier 1 is the absence of a standard session-scoping contract across agent frameworks, every framework (LlamaIndex, LangChain, Bedrock Agents) uses different field names and enforcement points, so teams must audit each integration separately.
  • The stateless isolation model (Anthropic Messages API) is Tier 1 at the API layer but remains Tier 2 at the application layer because the application session store is not standardised.

Last verified against upstream docs: 2026-05-30.