CVE-2019-5736 is a critical container escape vulnerability in runc, the low-level container runtime used by Docker, containerd, CRI-O, and by extension most Kubernetes clusters. The flaw allows a malicious or compromised container to overwrite the host's runc binary and execute arbitrary code as root on the underlying host — a full breakout from container isolation to host compromise. Because runc sits underneath nearly every mainstream container platform, the vulnerability had blast radius across the entire container ecosystem: any organization running untrusted images, multi-tenant clusters, or CI/CD build containers on an unpatched runtime was exposed to host takeover from a single malicious docker run or kubectl exec into an attacker-influenced container.
What Runc Does, and Why This Bug Mattered
runc is the OCI-compliant runtime that actually creates and starts containers — Docker and containerd both shell out to it to set up namespaces, cgroups, and the container's root filesystem before handing off execution to the containerized process. Because runc briefly runs with host privileges before it fully drops into the container's isolated context, any bug that lets a container-side process influence what runc does before that handoff is a direct path to the host. CVE-2019-5736 was exactly that kind of bug, which is why it was treated as a "stop what you're doing and patch" event across the industry in February 2019.
Affected Versions and Components
- runc: all versions prior to
1.0-rc6(the fix landed in the1.0-rc6release on February 18, 2019). - Docker Engine: versions prior to
18.09.2(Docker vendors runc internally). - containerd: versions prior to
1.2.4. - CRI-O: versions prior to
1.13.6/1.14.0. - Kubernetes: any cluster whose nodes ran an unpatched container runtime (kubelet itself was not directly vulnerable, but every node running affected Docker/containerd/CRI-O was).
- LXC: versions using an affected runc-equivalent exec path were also flagged by downstream distributions.
- Apache Mesos and other orchestrators that shelled out to vulnerable runc builds.
Because runc is vendored deep inside higher-level tools, many teams didn't realize they were exposed until they checked the effective runc version bundled in their Docker or containerd package — not just their orchestrator version. This is a recurring theme in container supply chain risk: the vulnerable component is rarely the thing you're monitoring directly.
Severity: CVSS, EPSS, and Exploitability Context
NVD rates CVE-2019-5736 at CVSS v3.1 base score 7.2 (High) — vector AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H. The "AV:L" (local attack vector) and "PR:H" (privileges required) look modest at first glance, but the Scope Changed (S:C) and High/High/High impact triad reflect the reality: an attacker who can get code running inside any container — including one they only indirectly influence, such as a CI job pulling an untrusted base image — can pivot to full host compromise. That gap between "looks locally scoped" and "is actually a host-root escape" is exactly why this CVE generated so much urgency despite a CVSS score that isn't in the 9-10 range.
At disclosure, working proof-of-concept exploit code was published almost immediately, and the vulnerability was actively weaponized in security research and red-team tooling within days. It predates CISA's Known Exploited Vulnerabilities (KEV) catalog (established in 2021), so it does not carry a KEV listing, but its real-world exploitability was never in doubt — it was demonstrated live against default Docker and Kubernetes configurations. Security teams should treat the absence of a KEV entry here as an artifact of timing, not as a signal of low risk; any legacy runc binary still in production today should be scored as if it were freshly disclosed.
How the Escape Works
The root cause is a classic time-of-check/time-of-use race combined with an unsafe use of /proc/self/exe. When runc executes a process inside a container, it re-executes itself via the /proc/self/exe symlink so the correct binary runs inside the new namespaces. A malicious container process can:
- Trick runc into executing a target binary (for example, by replacing
/bin/shinside the container with a specially crafted executable) that, when invoked, immediately loops back and opens/proc/self/exefor writing. - Because the container process and the host runc process share the same PID/mount context at that instant — before namespace transition fully completes — the container process obtains a writable file descriptor pointing at the host's runc binary on disk, not a namespaced copy.
- The attacker overwrites the host runc binary with malicious payload code through that descriptor.
- The next time any container on that host is started, stopped, or exec'd into — by any tenant, at any time — the corrupted runc binary runs as root on the host, giving the attacker arbitrary code execution outside all container boundaries.
The elegance (and danger) of the bug is that it requires no kernel exploit, no capability misconfiguration, and no privileged container flag — just the ability to influence what a container executes, which is trivially satisfied by pulling a poisoned public image or by exploiting an unrelated application-layer vulnerability to get shell access inside a container.
Disclosure Timeline
- Discovered by security researchers Adam Iwaniuk and Borys Popławski, who reported the issue to the runc maintainers in confidence in January 2019.
- Coordinated by runc maintainer Aleksa Sarai, who worked with Docker, Kubernetes SIG-Node, CRI-O, and major cloud providers on a private embargoed fix.
- February 11, 2019: Public disclosure occurred earlier than the planned coordinated date after details began circulating outside the embargo group, forcing an accelerated release of the advisory and mitigations.
- February 18, 2019: runc
1.0-rc6shipped with the official patch. - Late February 2019: Docker (
18.09.2), containerd, CRI-O, major Linux distributions, and managed Kubernetes providers (EKS, GKE, AKS) shipped patched runtime packages and node images in rapid succession. - 2019–present: The CVE has remained a staple reference point in container security training and audits, since unpatched legacy runc binaries continue to surface in stale golden images, embedded systems, and long-lived CI runners.
Remediation Steps
- Patch the runtime, not just the orchestrator. Upgrade runc to
1.0-rc6or later. If you run Docker, upgrade to18.09.2+. If you run containerd or CRI-O directly (common in Kubernetes), upgrade to1.2.4+and1.13.6+/1.14.0+respectively. - Rebuild node images. Kubernetes nodes bake the container runtime into the OS/AMI image — patching the control plane does nothing here. Rotate node pools onto images with an updated runtime rather than patching in place.
- Audit for vendored/embedded copies. CI runners, build agents, developer VMs, and appliance-style products frequently vendor an old Docker or runc binary. Inventory every place a container runtime exists, not just production clusters.
- Reduce blast radius with user namespaces. Enabling Docker/containerd user namespace remapping means even a successful escape lands as an unprivileged host user rather than root, significantly limiting post-escape impact.
- Prefer sandboxed runtimes for untrusted workloads. For multi-tenant or untrusted-image scenarios, gVisor or Kata Containers add a second isolation boundary that this class of runc-level bug cannot cross.
- Restrict what untrusted containers can execute. Seccomp profiles, read-only root filesystems, and dropped Linux capabilities won't stop this specific bug, but they shrink the pool of vulnerabilities an attacker can chain toward a similar escape.
- Verify image provenance before execution. Since exploitation starts with getting a malicious binary into a container's execution path, enforcing signed/attested images and blocking unverified public images reduces the odds this class of exploit ever gets a foothold.
How Safeguard Helps
Safeguard closes the gap between "a CVE exists" and "we know which of our workloads can actually be exploited by it." Our reachability analysis traces whether a vulnerable runc binary is actually on the execution path for containers that run untrusted or externally-sourced images, so security teams can triage CVE-2019-5736-class findings by real exploitability instead of chasing every match a scanner flags. Griffin, Safeguard's AI-driven security analyst, continuously cross-references your fleet's SBOM and running container inventory against advisories like this one, flagging stale runtime binaries embedded in golden images, CI runners, and node AMIs that traditional package scanners miss. Safeguard's SBOM generation and ingest pipeline gives you a single source of truth for exactly which hosts, node pools, and build agents carry an affected runc, containerd, or Docker version — even when it's vendored several layers deep. And where a fix is available, Safeguard can open auto-fix pull requests that bump the pinned runtime version in your Dockerfiles, base images, and infrastructure-as-code, turning a multi-team patch rollout into a reviewable, mergeable diff.