Capability & kernel escapes

SYS_ADMIN, /proc, and CVE-driven breakouts.

Advanced14 min · lesson 24 of 25

Beyond the big three, the deeper escapes abuse the fact that all containers share one kernel: an over-granted capability or a kernel vulnerability can cross the boundary directly. These are rarer and more technical, but understanding the classes tells you which capabilities to guard and why keeping the host patched is a container-security control, not just general hygiene.

Capability-driven escapes

A handful of capabilities are escape primitives on their own. CAP_SYS_ADMIN allows mount operations that have been chained into breakouts (the classic release_agent/cgroup technique needed SYS_ADMIN plus a writable cgroup mount). CAP_SYS_MODULE lets a container load a kernel module — instant, total host control. CAP_SYS_PTRACE with a shared PID namespace lets a container inspect and hijack host processes. CAP_DAC_READ_SEARCH has been used to read arbitrary host files. The through-line: these are exactly the capabilities cap-drop ALL removes, which is why the drop matters so much.

terminal
# the defense is verification: confirm production containers hold none of these
$ docker run --rm --cap-drop ALL alpine sh -c \
'apk add -q libcap; capsh --print | grep -E "sys_admin|sys_module|sys_ptrace|dac_read"' \
|| echo "none of the escape-grade caps present — good"
none of the escape-grade caps present — good

Kernel-vulnerability escapes

Because the kernel is shared, a kernel privilege-escalation bug reachable from a container syscall can be an escape — Dirty COW, Dirty Pipe, and various netfilter and io_uring flaws have all been demonstrated as container breakouts. There is no in-container configuration that fully fixes a kernel bug; the defenses are to reduce the syscalls that reach the kernel (seccomp), patch the host promptly, and for genuinely untrusted workloads put a stronger boundary around the kernel entirely — which is the next lesson.

Deeper escapes and their real defenses
capability abuse
SYS_ADMIN / SYS_MODULE
defense: cap-drop ALL
SYS_PTRACE + shared pid
defense: no shared namespaces
kernel bugs
Dirty Pipe / COW, etc.
defense: seccomp + patch host
untrusted code
defense: sandbox the kernel
seccomp shrinks the reachable syscall surface; patching closes known bugs; a sandbox contains the unknown ones.
A shared kernel is the ceiling on container isolation
No amount of in-container hardening changes the fact that a container and the host use the same kernel, so a sufficiently powerful kernel exploit can always, in principle, escape. That is not a reason to skip hardening — it raises the bar enormously — but it is why truly untrusted or multi-tenant workloads warrant a sandbox that gives them a separate kernel boundary.