try.directtry.direct

Docker AI Agents: Isolation, Security & MCP

AI agents are no longer confined to chat windows. They read files, call APIs, write to databases, and execute code autonomously. That changes the security model entirely. A misconfigured agent is not just a buggy service; it is a privileged process that handles untrusted input and has broad tool access by design.

This guide covers three layers that actually matter: why standard Docker containers are not enough, how gVisor and Kata Containers raise the isolation floor, and how Docker's MCP Toolkit lets you enforce least-privilege at the tool layer.


1. Why Standard Docker Containers Are Not Enough


Docker containers isolate through Linux namespaces, cgroups, and seccomp, but they share the host kernel. Every container on a host calls into the same kernel. That is a fine trade-off for a trusted web server. It is a significant one for a process that dynamically generates and executes code based on external input.

The threat model for an AI agent looks like this:

  • Container escape (MITRE ATT&CK T1611): a kernel vulnerability or misconfiguration gives an attacker host-level access, reaching every other container on the machine.
  • Prompt injection leading to RCE: an agent receives a malicious instruction and executes it through a shell tool.
  • Tool poisoning: hidden directives embedded in MCP tool metadata are visible to the model but not to the user.
  • Credential exfiltration: an agent with filesystem access can read .env files, ~/.aws/credentials, or service account tokens.

Real-world baseline: A 2025 academic survey of over 1,800 deployed MCP server implementations found that more than 30% had at least one exploitable vulnerability. Endor Labs analysis of 2,614 MCP implementations found that 82% use file operations prone to path traversal and 34% use APIs susceptible to command injection.


CVE-2024-21626 ("Leaky Vessels") showed the concrete risk of shared-kernel runtimes: a process inside a container could set its working directory to /proc/self/fd/7, a leaked file descriptor pointing at the host filesystem, and achieve a full container escape. Affected all runc versions up to 1.1.11, patched in 1.1.12.


2. Stronger Runtimes: gVisor and Kata Containers


gVisor: a kernel in user-space

gVisor is a Google open-source project that implements the Linux kernel in user-space. A component called Sentry intercepts all syscalls before they reach the host kernel and handles them in an isolated process. From the container's perspective everything looks normal. From the host's perspective, no direct kernel calls ever happen.

Installation requires a single binary (runsc) registered in daemon.json. Any existing image runs without changes since it is OCI-compatible. The overhead is roughly 10 to 30% on I/O-heavy workloads and minimal on compute-heavy ones.


// JSON | /etc/docker/daemon.json
{
  "runtimes": {
    "runsc": { "path": "/usr/local/bin/runsc" }
  } 
}

json


# YAML | docker-compose.yml (gVisor runtime) 
services:
  ai-agent:
    image: my-agent:latest  
    runtime: runsc

yaml


Kata Containers: a micro-VM per container

Kata Containers wraps each container in a lightweight VM with its own Linux kernel via KVM. The hardware boundary eliminates an entire class of kernel-based attacks since there is no shared kernel to escape to. It is OCI-compatible and works with Docker Compose with a single runtime field change.

The trade-offs are cold starts of roughly 100 to 300ms, around 100 MB of extra RAM per container, and no support on macOS or WSL2 (you need bare metal or a cloud instance with nested virtualization). GPU passthrough works with Kata 3.x via VFIO.


# YAML | docker-compose.yml (Kata Containers runtime) 
services:
  ai-agent:
    image: my-agent:latest  
    runtime: kata-qemu   # or kata-fc (Firecracker, faster cold start)  
    cap_drop: [ALL]  
    read_only: true  
    security_opt:
      - no-new-privileges:true

yaml

How to choose: use gVisor for high-I/O agents where simpler setup matters and a user-space kernel boundary is sufficient. Use Kata Containers when agents execute untrusted, LLM-generated code in production, since the dedicated kernel eliminates the kernel escape vector entirely. Standard runc is appropriate only for agents running fully trusted, reviewed code.


3. Docker MCP Toolkit: Least Privilege at the Tool Layer


Model Context Protocol (MCP) is Anthropic's open standard for connecting LLMs to external tools and data sources. Docker's MCP Toolkit, announced in April 2025 and released in beta in June 2025, solves three problems at once: tool discovery through a catalog of 300+ verified servers on Docker Hub, isolation where each MCP server runs as its own container, and credential management through a Gateway proxy rather than environment variables.


The three components

MCP Catalog is a curated registry on Docker Hub with automated testing and scanning. Currently over 300 verified servers including Stripe, Elastic, Neo4j, New Relic, Grafana, and many others.

MCP Toolkit is a Docker Desktop extension for managing server profiles and launching containers. Credentials are stored in Docker Desktop's secure store rather than in environment variables, reducing the risk of accidental exposure through logs or environment dumps.

MCP Gateway is an open-source proxy between MCP clients and servers that enforces policy on every tool call. It handles server lifecycle management, request routing, authentication, logging, and call tracing.


Key principle: By treating each tool as a separate MCP server container, you re-introduce least privilege. Instead of giving an agent broad access, you allow only the smallest set of capabilities it needs. The Gateway enforces this per-call and provides full audit visibility over every tool invocation.


Hardened Compose config


# YAML | docker-compose.yml (hardened MCP stack) 
version: "3.9" services:
  mcp-server:
    image: mcp/wikipedia:latest@sha256:<digest> # pin by digest, not tag  
    runtime: runsc                               # gVisor runtime  
    read_only: true  
    tmpfs:
      - /tmp:size=64m,noexec  
    cap_drop: [ALL]  
    security_opt:
      - no-new-privileges:true  
    user: "1000:1000"  
    networks: [mcp-net]   
    
  mcp-gateway:
    image: docker/mcp-gateway:latest  
    ports: ["127.0.0.1:8811:8811"]  
    volumes:
      - ./policy.yaml:/config/policy.yaml:ro  
    networks: [mcp-net]  
    
 networks:
   mcp-net:
     internal: true # no outbound internet by default

yaml


4. MCP Attack Patterns You Need to Know


Tool poisoning

Tool poisoning is a demonstrated attack class first documented publicly by Invariant Labs in April 2025. An attacker who controls an MCP server writes directives directly into tool descriptions or JSON Schema metadata. The model reads this as trusted configuration and executes hidden commands while the user sees nothing unusual. Because these fields arrive at boot as what looks like system configuration, they bypass the mental model most developers have of injection attacks.

The rug pull variant is subtler: a tool's description looks benign on day one, then quietly changes on day seven to redirect API keys to an attacker. MCP clients should alert on any change to tool descriptions after installation.


MCPoison: CVE-2025-54136

MCPoison (CVE-2025-54136, CVSS 7.2) is a related but distinct vulnerability discovered by Check Point Research in Cursor IDE. Once a user approved an MCP configuration file, Cursor never re-validated it on subsequent opens. An attacker with write access to a shared repository could commit a benign config, wait for approval, then silently swap in a malicious payload. Every subsequent Cursor launch would execute the attacker's commands with no warning. Fixed in Cursor 1.3, released July 29, 2025.


Supply chain: CVE-2025-6514

mcp-remote is a popular OAuth proxy for connecting local MCP clients to remote servers. JFrog Security Research discovered a critical OS command injection flaw (CVSS 9.6/10) in all versions from 0.0.5 up to 0.1.16. A malicious MCP server could send a crafted authorization_endpoint URL that mcp-remote passed directly to the system shell, achieving RCE on the client machine. The package had been downloaded over 437,000 times at the time of disclosure. Fixed in version 0.1.16.


Mitigation: Pin all images by sha256 digest, not by tag. Use only servers from the Docker MCP Catalog with passed verification. Enable signature verification in MCP Gateway. Alert on any change to tool descriptions. Keep mcp-remote at 0.1.16 or later.


Cross-server hijacking

When multiple MCP servers connect to the same agent, a malicious server can attempt to override or intercept calls to a trusted one through the model's context window. Network isolation between servers through an internal Docker network with gateway routing limits this attack surface structurally, since servers cannot reach each other without going through the Gateway policy layer.


5. Kubernetes: RuntimeClass for Per-Workload Isolation


For teams running agents on Kubernetes, RuntimeClass lets you assign an isolation level per Pod without changing container images.


# YAML | kata-runtime-class.yaml 
apiVersion: node.k8s.io/v1 
kind: RuntimeClass 
metadata:
  name: kata-containers 
handler: kata-qemu

yaml


# YAML | agent-pod.yaml 
apiVersion: v1 
kind: Pod 
metadata:
  name: ai-agent 
spec:
  runtimeClassName: kata-containers  
  containers:
    - name: agent  
      image: my-agent:latest  
      securityContext:
        runAsNonRoot: true  
        readOnlyRootFilesystem: true  
        allowPrivilegeEscalation: false  
        capabilities:
          drop: ["ALL"]

yaml

Google's Agent Sandbox, a project contributed to CNCF under Kubernetes SIG, is building a standard for agentic workload isolation with gVisor and Kata Containers as pluggable backends. Not yet GA, but worth tracking if you already operate Kubernetes at scale.


6. Production Security Checklist


  • Use gVisor or Kata Containers. Never use standard runc for code-executing agents.
  • Never run containers with --privileged. Drop ALL capabilities and add back only what is needed.
  • Set read_only: true on the container filesystem. Mount tmpfs for /tmp with noexec.
  • Bind MCP services to 127.0.0.1 only. Use an internal Docker network with no default egress.
  • Pin every image by sha256 digest. Never deploy from a mutable tag in production.
  • Store credentials in Docker Secrets or an external vault, not in environment variables.
  • Log all tool calls through MCP Gateway. Redact secrets before they reach the model.
  • Alert on changes to tool descriptions. This is your rug pull detector.
  • Keep mcp-remote at version 0.1.16 or later. Audit all MCP-related npm packages regularly.

FAQ


What is Docker MCP and why does it matter for AI agents?

Docker MCP Toolkit is Docker's solution for running MCP servers as isolated containers with managed credentials and policy enforcement. Without it, MCP servers typically run directly on the host with access to the full filesystem. The Toolkit adds a catalog of 300+ verified servers, per-server container isolation, and an open-source Gateway proxy that enforces policy on every tool call and provides full call tracing.


What is the difference between gVisor and Kata Containers?

gVisor implements a Linux kernel in user-space so syscalls are intercepted by an isolated process instead of reaching the host kernel directly. Kata Containers goes further: each container gets its own micro-VM with a dedicated Linux kernel via KVM. gVisor is simpler to set up and works on most environments including cloud VMs; Kata gives stronger, hardware-enforced isolation and is the right choice when agents run untrusted, LLM-generated code in production.


Do I need a different container image for gVisor or Kata?

No. Both runtimes are OCI-compatible. Your existing images run without any changes. You only add a single runtime field to your Compose file or daemon.json.


What is MCP tool poisoning?

Tool poisoning embeds malicious instructions in an MCP tool's descriptions or JSON Schema metadata rather than in user input. The model reads this as trusted system configuration and executes the hidden directives. Invariant Labs first documented this attack class in April 2025. Defense includes using only catalog-verified servers pinned by digest, enabling Gateway policy enforcement, and monitoring for any changes to tool descriptions after initial installation.


What was CVE-2025-6514?

CVE-2025-6514 was a critical (CVSS 9.6) OS command injection vulnerability in mcp-remote, a widely used npm package for connecting MCP clients to remote servers via OAuth. A malicious MCP server could craft an authorization_endpoint URL that mcp-remote passed directly to the system shell. Discovered by JFrog Security Research, disclosed July 9, 2025, and fixed in mcp-remote version 0.1.16.


Conclusion


AI agents are privileged processes that handle untrusted input. Standard Docker container isolation was not designed for this threat model.

The practical floor for production in 2026 is gVisor for I/O-heavy agents, Kata Containers for anything executing untrusted code, Docker MCP Gateway as the policy enforcement point for every tool call, and digest-pinned images throughout. The MCP ecosystem is maturing fast and so is its CVE list. The tools to defend it exist today. The gap is architectural decisions, not missing technology.