CoursesRuntime & eBPF securityContainer escapes & IR

Container escape paths

Privileged, hostPath, sockets, caps, runtime CVEs.

Expert35 min · lesson 13 of 15

To defend against container escapes you have to understand how they work — and almost all of them come down to a misconfiguration that hands the container a piece of the host, or a bug in the software that enforces the boundary. Very few are exotic; most are things admission policy could have blocked.

The misconfiguration escapes

The common escapes exploit privilege the container should never have had. A privileged container has all capabilities and host device access — effectively the host. Mounting the Docker/containerd socket lets the container drive the runtime and launch a privileged sibling. A hostPath mount of / (or the kubelet directory) exposes host files: credentials, kubelet certs, cron. Dangerous capabilities like CAP_SYS_ADMIN re-enable mounts and namespace operations used in escape chains; CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH open others. Sharing host namespaces (hostPID, hostNetwork) collapses isolation. Each of these is a deliberate setting that admission policy can and should forbid.

the manifest patterns that enable escape
# Every one of these is an escape enabler — forbid by admission policy:
securityContext: { privileged: true } # all caps + host devices
volumes:
- hostPath: { path: / } # host filesystem access
- hostPath: { path: /var/run/docker.sock } # drive the runtime → host root
hostPID: true # see/enter host processes
hostNetwork: true # host network stack
capabilities: { add: ["SYS_ADMIN"] } # "the new root"
# Baseline defense: Pod Security Admission "restricted" rejects all of the above.

The runtime and kernel bug escapes

The other class exploits bugs in the boundary itself. Container-runtime CVEs — runc’s CVE-2019-5736 (overwriting the host runc binary) and the 2024 "Leaky Vessels" (CVE-2024-21626) — let a crafted image or config break out even from an unprivileged container, which is why patching runtimes promptly matters. And because containers share the host kernel, a kernel privilege-escalation vulnerability is a shared escape surface: one bug can undermine every container on the node. For untrusted or multi-tenant workloads, a stronger boundary (gVisor’s user-space kernel, or Kata’s lightweight VMs) shrinks that shared surface.

How containers escape
misconfiguration
privileged / hostPath / socket
host handed to the container
dangerous caps / host namespaces
isolation re-opened
boundary bugs
runtime CVEs (runc)
crafted image/config breaks out
kernel vulns
shared kernel = shared surface
stronger isolation
gVisor / Kata
shrink the shared surface
Most escapes are preventable misconfigurations; the rest are patchable bugs. Forbid the enablers, patch the boundary, isolate the untrusted.
The Docker socket is host root
Mounting /var/run/docker.sock (or the containerd socket) into a container — even read-only — hands it control of the runtime, and thus the host. It is a frequent "convenience" in CI and tooling images and one of the most reliable escapes. Never mount the runtime socket into a workload; use a proper build/exec API with scoped auth instead.