The one-sentence version
"Container escape" refers to a program running inside a container breaking through isolation to gain control over the host machine. The vast majority of escapes do not require sophisticated vulnerabilities but are caused by loose configurations: running in privileged mode, mounting the Docker control interface into the container, granting unnecessary kernel capabilities, or mounting sensitive host directories. The remaining minority are true vulnerabilities: flaws in the container runtime (such as runc) or the Linux kernel itself. For AI Agents, this means: putting an Agent in a container does not automatically make it secure; configuration is everything.
This article has three layers:
- Layer 1: The Intuition: The door lock is fine, but you hung a spare key on the inside of the door.
- Layer 2: Real-World Use: Two famous runc vulnerabilities, kernel vulnerabilities, and common forms of misconfiguration.
- Layer 3: Root causes of escape, hardening checklists, and how to detect them.
Layer 1: The Intuition
1.1 The lock is fine, but the key is hanging inside
A room's door lock is very sturdy, but for convenience:
- A master key is left inside the room (privileged mode);
- A window opens directly into the building's control room on the room's wall (Docker socket);
- One wall of the room is actually the wall of another room (mounting host directories).
The person living inside doesn't need to pick the lock; they can just walk out.
1.2 Two types of causes
| Category | Proportion | Examples |
|---|---|---|
| Misconfiguration | The vast majority | Privileged mode, mounting Docker socket, excessive capabilities, mounting sensitive host directories, running as root |
| Software Vulnerabilities | A minority, but high impact | Container runtime vulnerabilities, Linux kernel vulnerabilities |
Layer 2: Real-World Use
| Event | Type | Description |
|---|---|---|
| runc CVE-2019-5736 | Runtime vulnerability | A malicious process inside a container can overwrite the runc binary on the host; the next time someone executes a container command on the host, the attacker's code will run. Affects almost all platforms using runc, such as Docker and Kubernetes. |
| Leaky Vessels (2024, including runc CVE-2024-21626) | Runtime vulnerability | A set of vulnerabilities, the most serious of which relates to file descriptor leakage, allowing container processes to access the host filesystem. |
| Dirty Pipe (2022, CVE-2022-0847) | Kernel vulnerability | A vulnerability in the Linux kernel's pipe mechanism that allows overwriting read-only files, which can be used for privilege escalation and container escape. |
| Cryptocurrency mining incidents (Numerous) | Misconfiguration | Attackers scan the internet for unauthenticated, exposed Docker APIs or Kubernetes dashboards to directly create privileged containers for mining. |
These runtime and kernel vulnerabilities were all patched quickly after disclosure. Timely updates are the most basic line of defense.
Layer 3: Principles and Engineering
3.1 Common forms of misconfiguration
| Configuration | Why it is dangerous |
|---|---|
--privileged |
Almost disables all isolation: can access all devices and possesses all kernel capabilities. |
Mounting /var/run/docker.sock |
Programs inside the container can control Docker on the host, creating a new container that mounts the host's root directory. |
Adding high-risk capabilities like CAP_SYS_ADMIN |
This capability covers a vast range of privileged operations and is often referred to as "the new root." |
Mounting host /, /etc, /proc, /sys, or user home directories |
Direct read/write access to host files. |
| Sharing host PID or network namespaces | Can see and affect host processes and networking. |
| Running as root in a container without enabling user namespaces | Once escaped, the attacker is root on the host. |
| Cloud metadata interface is reachable | The container can obtain temporary credentials for the cloud instance where the host resides (see "SSRF"). |
For AI programming Agents, a particularly common temptation is: to allow the Agent to "build Docker images," the Docker socket is mounted into the Agent's container. This is equivalent to handing over control of the host to the Agent.
3.2 Hardening Checklist
| Measure | Description |
|---|---|
| Do not use privileged mode; do not mount the Docker socket | When building images is required, use daemonless build tools or a separate build service. |
| Drop all capabilities, then add only what is needed | --cap-drop=ALL |
| Run as a non-root user; enable user namespaces (rootless) | Even if an escape occurs, the attacker is not host root. |
| Use default or stricter seccomp / AppArmor / SELinux configurations | Limits system calls and file access. |
| Read-only root filesystem | --read-only, provide only necessary writable temporary directories. |
no-new-privileges |
Prevents privilege escalation via setuid programs. |
| Resource limits | CPU, memory, process count; prevents exhaustion of host resources. |
| Block cloud metadata interfaces | Or force the use of IMDSv2 which requires a token. |
| Timely updates of kernel and runtime | Patches for runtime and kernel vulnerabilities are usually released quickly. |
| Use stronger isolation for untrusted code | gVisor, micro-VMs (see "Layers of a sandbox"). |
3.3 Detection
- Configuration Scanning: Use tools before deployment to check if container and Kubernetes configurations contain the high-risk items mentioned above;
- Runtime Monitoring: Use tools like Falco to monitor abnormal behavior inside containers, such as starting a shell in a container, accessing the Docker socket, modifying sensitive files, or loading kernel modules;
- Regular Red Teaming: Simulate "Agent has been fully compromised" in a test environment to see how far it can go (see "Threat Modeling and Red Teaming").
3.4 The one-sentence principle
A container is not a security boundary designed for "running untrusted code"; it is primarily a packaging and resource isolation tool. To run truly untrusted code (including anything an AI Agent might write after a prompt injection), you must add another layer of stronger isolation outside the container.
Summary
| Layer | Key points |
|---|---|
| Intuition | The lock is sturdy, but the key is hanging inside (misconfiguration) |
| Two root causes | Misconfiguration (majority), runtime and kernel vulnerabilities (minority) |
| High-risk configurations | Privileged mode, Docker socket, high-risk capabilities, mounting host directories, running as root |
| Hardening | Drop capabilities, non-root, read-only, seccomp, timely updates, stronger isolation for untrusted code |