← Atlas · Principles Reference in Helmwart

Secure-design classics · S&S 1975

Least Common Mechanism

Minimise mechanism shared across users/agents. Shared resources let a compromise of one contaminate all.

Why it matters for agentic AI

Saltzer and Schroeder’s least-common-mechanism principle is about shared infrastructure. When two principals share a mechanism (a file, a table, a service), a compromise that affects the mechanism affects both. The principle’s prescription is to minimise the scope of what is shared: give each principal its own mechanism where possible, and where sharing is unavoidable treat the shared component as a high-value target requiring its own hardening. Containment sets the blast radius after a shared mechanism is compromised; least-common-mechanism reduces how many agents are in that radius.

In 1975 the canonical concern was a shared subroutine library that could be tampered with to affect every user who linked it. The agentic analogue is more insidious because the contamination mechanism is semantic rather than code-level. A shared vector store is a mechanism shared by every agent that reads from it. A shared tool registry is a mechanism shared by every agent that discovers tools from it. A shared base system prompt is a mechanism shared by every agent instantiated from it. In each case, a single successful compromise (poisoning a document into the vector store, inserting a malicious entry into the registry, injecting into the shared prompt) propagates to every agent that reads from that mechanism, without any agent-to-agent communication.

This propagation dynamic is the feature of agentic least-common-mechanism that has no close classical analogue. In a traditional system, contaminating a shared library requires code modification and typically produces detectable artefacts. Poisoning a shared RAG corpus requires only that an attacker can contribute a document to the data pipeline. That is a far lower bar, especially in systems that ingest from the web, email, or user-supplied files. And because the retrieval is semantic (nearest-neighbour, not exact-match), a small number of carefully crafted documents can reliably surface for a targeted query across a large corpus, even when those documents are otherwise invisible among millions of legitimate entries.

The design response is to refuse unnecessary sharing before it occurs. Per-tenant memory namespaces mean that contamination introduced through one tenant’s data pipeline cannot reach another tenant’s context. Per-task memory scope means that a poisoned entry planted during one session cannot be retrieved in a later, unrelated session. Separate MCP instances per trust boundary mean that a malicious tool server granted access at one trust level cannot serve tools to agents operating at a higher level.

Scenario: fleet-wide RAG poisoning

A customer-support platform runs fifty agents, all reading from one shared vector store that ingests customer-submitted documentation. An attacker submits a document that, when retrieved, carries hidden instructions embedded in its text. Because retrieval is semantic, the document surfaces reliably for queries related to a common product category, the one the attacker wants to manipulate. Within hours, every agent handling queries in that category ingests the poison and begins following the embedded instruction. The blast radius is fifty agents and every customer they serve. Per-tenant namespaces would have contained it to a single company’s agents; per-task scope would have limited it to sessions that actively retrieved from that category. Neither would have depended on detecting the malicious document before ingestion.

Scenario: the shared tool registry

A platform offers a curated MCP tool registry that all agents in the organisation discover from. A third-party tool server in the registry is updated to embed a hidden instruction in its tool description after its initial security review. This is a rug-pull. Every agent that queries the registry now receives a tool description containing that instruction, and the model, which sees tool descriptions as trusted structured input, acts on it. The shared registry is the common mechanism: one successful post-approval modification affects every consumer. Separate MCP instances per trust boundary mean only agents at the affected trust tier are exposed. Runtime re-verification of tool descriptions (hash comparison against an approved manifest) catches the change before the instruction reaches any agent’s context.

How it fails

  • RAG poisoning propagates across a whole fleet because every agent reads one shared vector store; one bad document affects every agent that retrieves from its neighbourhood.
  • A malicious or compromised server in a shared tool registry serves its payload to every agent that discovers tools from that registry.
  • One tenant’s content contaminates another’s via a shared retrieval index; the boundary between tenants exists only in the application layer, not in the store.
  • A shared long-term memory store lets one agent’s persisted conclusions influence another agent’s context in a later, unrelated session.

Why the mapped controls work

Per-user/tenant/task memory namespaces instantiate least-common-mechanism at the retrieval layer: each namespace is a separate mechanism with its own access token, so poisoning one requires separate effort for each, and a successful poison affects only the namespace it entered. Curated signed registries with version pinning mean the tool registry is a controlled mechanism rather than an open append surface; signatures allow runtime re-verification so a post-approval change is detectable before it propagates. Ingestion filtering with provenance treats the ingestion pipeline as a choke point: content is attributed and checked before it enters the shared mechanism, reducing the chance of a poison entry surviving to the retrieval stage. Separate MCP instances per trust boundary are the structural form of the principle: agents at different trust levels have different mechanisms, so a compromise at one level is bounded by the boundary.

First steps

  1. Partition your vector store into per-tenant and per-task namespaces today using your store’s native collection or namespace mechanism (e.g. Qdrant collections, Pinecone namespaces, Chroma collections), issue a separate access token per namespace, and verify that a query authenticated with tenant A’s token cannot retrieve results from tenant B’s namespace.
  2. Add a hash-based ingestion check to your document pipeline: compute and store a SHA-256 of every ingested document at ingest time, and run a nightly job that re-hashes the stored content and alerts on any mismatch. This catches post-ingestion tampering before it reaches agent retrieval.
  3. Deploy separate MCP server instances for agents operating at different trust boundaries (e.g. internal-only agents versus agents that process user-supplied content) rather than sharing one instance, and enforce the separation at the network layer so an agent at the lower trust boundary cannot reach the higher-trust MCP instance regardless of what its prompt instructs.

Threats it governs

When this principle is absent, these threats become reachable.

Controls that advance it

Catalogue mitigations that strengthen this principle, grouped by the defence-in-depth stage they sit in.

Prevent
  • Session isolation 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.
  • Cross-client isolation 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.
  • Shared-memory ACL When multiple agents share a single vector store, the access boundaries between them are not enforced by the store itself unless you configure them explicitly. Without per-namespace write and retrieval controls, an agent that can write to the shared corpus can insert crafted vectors into any namespace it can reach, and any agent that can query the store can retrieve another agent's confidential documents through embedding-space proximity. Shared-memory ACL addresses this by tagging every vector with a principal identifier at write time and filtering every retrieval query to the requesting agent's namespace, enforced at the gateway layer where the agent cannot bypass it.
  • Vector ACL A vector store returns results by embedding-space proximity, not by who is asking. Without a per-principal filter applied before similarity ranking, a query from tenant A can surface tenant B's vectors if the embeddings are close enough. Vector ACL closes that gap: every retrieval call is scoped to the requesting principal's namespace or payload partition before the store ranks any results, so cross-principal hits are structurally impossible rather than merely unlikely.
Detect

No catalogued control.

Respond

No catalogued control.

In Helmwart

The design root beneath the Q2 propagation view; not scored on its own.