Safeguard
Vulnerability Analysis

CVE-2024-21626: runc process.cwd Container Breakout Deep ...

A technical breakdown of CVE-2024-21626, the runc process.cwd() flaw enabling container breakout to host access, with detection and remediation guidance.

Vikram Iyer
Security Researcher
7 min read

In late January 2024, the runc maintainers disclosed CVE-2024-21626, a container breakout vulnerability rooted in how the runc CLI handles the internal working directory (process.cwd()) during container startup and exec operations. The flaw allows an attacker who controls a container image or an exec command to cause a leaked host file descriptor to become the container process's current working directory, giving that process a path back onto the host filesystem. In the worst case, a malicious or compromised container can use this to read, write, and potentially execute code on the underlying host — a full breach of the container isolation boundary that most workloads assume is inviolable.

Because runc is the low-level OCI runtime underneath Docker Engine, containerd, CRI-O, and by extension most Kubernetes node runtimes, this was not a niche bug affecting one product. It touched the plumbing shared by nearly the entire container ecosystem.

What actually breaks

runc is responsible for the final step of "becoming" a container: setting up namespaces, cgroups, mounts, and the process's working directory before handing control to the containerized entrypoint. Internally, runc sometimes opens file descriptors on the host side of the mount namespace switch — for example, an fd pointing at the host root filesystem used briefly while it wires up the container's own root.

Under specific conditions, one of these internal file descriptors was left open and reachable from inside the container's own /proc/self/fd/ tree after the pivot into the container's namespace completed. If an attacker could influence the container's working directory — either through a crafted image WORKDIR or a docker exec --workdir / runc exec --cwd argument — they could point cwd at that leaked descriptor (something like /proc/self/fd/7). Because the descriptor still referenced the host's filesystem view rather than the container's, the container process effectively gained a working directory rooted outside its jail. From there, depending on privileges, an attacker could traverse and modify host files, which chains into full host compromise.

Security researcher Rory McNamara at Snyk identified this issue as part of a broader research effort into container build and runtime internals; Snyk grouped it with three related disclosures (CVE-2024-23651, CVE-2024-23652, CVE-2024-23653, primarily affecting BuildKit) under the collective name "Leaky Vessels." CVE-2024-21626 was the runc-specific and arguably most consequential of the four, since runc sits underneath so much of the ecosystem.

Affected versions and components

  • runc: versions up to and including 1.1.11 are affected. The fix shipped in runc 1.1.12.
  • Docker Engine: versions bundling vulnerable runc releases were affected; Docker shipped patched Engine and Desktop releases alongside the runc fix.
  • containerd: consumers of vulnerable runc binaries inherited the exposure; containerd-based platforms needed the updated runc shim.
  • Kubernetes: any cluster whose nodes ran an unpatched container runtime (via Docker, containerd, or CRI-O) was indirectly exposed, since kubelet delegates to these runtimes.
  • CRI-O and other OCI-runtime consumers, plus managed platforms and cloud providers that bundle runc, issued their own advisories and patched images.

The practical exposure window for any given environment depended less on Kubernetes or Docker version numbers directly and more on which runc binary was actually installed on the node or host — a detail that is easy to lose track of in large, heterogeneous fleets.

Severity, exploitability, and known exploitation

CVE-2024-21626 was rated High severity, with NVD's CVSS v3.1 base score commonly cited around 8.6, reflecting that a successful exploit can escalate from container-level access to host-level compromise — a scope change that significantly amplifies impact even though the initial access vector (control over a container image or an exec invocation) is itself fairly attainable in many CI/CD and multi-tenant environments.

At the time of disclosure, there was no public evidence of in-the-wild exploitation, and the issue was addressed via coordinated disclosure before technical exploit details were widely circulated. We are not treating this post as an authoritative source on whether the vulnerability has since been added to CISA's Known Exploited Vulnerabilities (KEV) catalog or on its current EPSS score — those values change over time, and readers should check CISA's KEV catalog and FIRST's EPSS feed directly for the latest status rather than relying on a static blog post. What's clear regardless of KEV/EPSS status is that any bug allowing routine container-boundary bypass in the default OCI runtime warrants prioritized patching, given how central runc is to container isolation guarantees across the industry.

Timeline

  • Rory McNamara (Snyk) identified and privately reported the runc process.cwd() issue to the runc maintainers as part of the broader "Leaky Vessels" research.
  • Coordinated disclosure followed involving the runc project, Docker, and other downstream consumers so that patches could be prepared before public release.
  • On January 31, 2024, the runc project and Snyk publicly disclosed CVE-2024-21626 alongside the related BuildKit CVEs, and runc 1.1.12 was released containing the fix.
  • Downstream projects and vendors — Docker Engine, containerd-based platforms, Kubernetes distributions, and major cloud providers — published corresponding advisories and shipped updated packages and node images in the days following disclosure.

Remediation steps

  1. Identify your runc version everywhere it runs — on Kubernetes nodes, CI runners, developer machines, and any bare Docker hosts. Don't assume Docker or Kubernetes version alone tells you the runc version; check the actual binary or the container runtime package.
  2. Upgrade to runc 1.1.12 or later. For most environments this means upgrading Docker Engine, containerd, or CRI-O to a release that bundles the patched runc rather than patching runc in isolation.
  3. Patch Kubernetes nodes by rolling updated node images or container runtime packages across the fleet, prioritizing nodes that run untrusted or multi-tenant workloads first.
  4. Audit build pipelines and CI systems that build or run containers from third-party or user-supplied Dockerfiles, since WORKDIR and exec --workdir are exactly the vectors this bug relies on.
  5. Consider defense-in-depth runtimes such as gVisor or Kata Containers for genuinely untrusted workloads — sandboxed and VM-isolated runtimes are not subject to this specific runc code path.
  6. Restrict who can supply container images and exec into running containers in shared clusters, since both are practical entry points for this class of attack.
  7. Verify remediation by confirming the deployed runc version on every node and runtime, not just by checking a package manifest — supply chain drift between "what we think we shipped" and "what's actually running" is exactly where vulnerabilities like this linger.

How Safeguard Helps

CVE-2024-21626 is a good illustration of why container security can't stop at "scan the application image." The vulnerable component here is the runtime underneath the container, not code your teams wrote or dependencies pinned in a manifest — which means it's invisible to source-level SCA tools and easy to miss in asset inventories that only track application artifacts.

Safeguard's supply chain security platform is built to close exactly that visibility gap:

  • Runtime and infrastructure component inventory: Safeguard identifies the actual runc, containerd, and container runtime versions deployed across your nodes and build infrastructure — not just what's declared in a manifest — so a CVE like this maps directly to the hosts and clusters that need patching.
  • Continuous CVE correlation: as new vulnerabilities like CVE-2024-21626 are disclosed, Safeguard cross-references your live environment against affected version ranges and surfaces exposure immediately, rather than waiting for a quarterly audit.
  • Build pipeline attestation: Safeguard tracks the provenance and runtime environment used to build and run your container images, making it possible to prove which runtime version handled a given build or deployment — critical when investigating whether a specific workload was ever exposed.
  • Policy enforcement: teams can set policies that block deployments onto nodes running known-vulnerable container runtimes, preventing regression even as new nodes are provisioned.
  • Prioritization by real exposure: rather than treating every CVE as equally urgent, Safeguard factors in reachability — for instance, whether your clusters accept untrusted images or third-party exec access — so remediation effort goes first to the environments where a bug like this is actually exploitable.

Container runtime CVEs like CVE-2024-21626 will keep surfacing because the isolation guarantees containers rely on are implemented in relatively low-level, high-privilege code. The organizations that respond fastest are the ones with continuous, accurate visibility into exactly what runtime code is running where — which is the problem Safeguard is built to solve.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.