Summary
mount destinations can be swapped via symlink-exchange to cause mounts outside the rootfs
runc 1.0.0-rc94 and earlier are vulnerable to a symlink exchange attack whereby
an attacker can request a seemingly-innocuous container configuration that
actually results in the host filesystem being bind-mounted into the container
(allowing for a container escape). CVE-2021-30465 has been assigned for this
issue.
An attacker must have the ability to start containers using some kind of custom
volume configuration, and while recommended container hardening mechanisms such
as LSMs (AppArmor/SELinux) and user namespaces will restrict the amount of
damage an attacker could do, they do not block this attack outright. We have a
reproducer using Kubernetes (and the below description mentions
Kubernetes-specific paths), but this is not a Kubernetes-specific issue.
The now-released runc v1.0.0-rc95 contains a fix for this issue, we
recommend users update as soon as possible.
Details
In circumstances where a container is being started, and runc is mounting
inside a volume shared with another container (which is conducting a
symlink-exchange attack), runc can be tricked into mounting outside of the
container rootfs by swapping the target of a mount with a symlink due to a
time-of-check-to-time-of-use (TOCTTOU) flaw. This is fairly similar in style to
previous TOCTTOU attacks (and is a problem we are working on solving with
libpathrs).
However, this alone is not useful because this happens inside a mount namespace
with MS_SLAVE propagation applied to / (meaning that the mount doesn't
appear on the host -- it's only a "host-side mount" inside the container's
namespace). To exploit this, you must have additional mount entries in the
configuration that use some subpath of the mounted-over host path as a source
for a subsequent mount.
However, it turns out with some container orchestrators (such as Kubernetes --
though it is very likely that other downstream users of runc could have similar
behaviour be accessible to untrusted users), the existence of additional volume
management infrastructure allows this attack to be applied to gain access to
the host filesystem without requiring the attacker to have completely arbitrary
control over container configuration.
In the case of Kubernetes, this is exploitable by creating a symlink in a
volume to the top-level (well-known) directory where volumes are sourced from
(for instance,/var/lib/kubelet/pods/$MY_POD_UID/volumes/kubernetes.io~empty-dir), and then
using that symlink as the target of a mount. The source of the mount is an
attacker controlled directory, and thus the source directory from which
subsequent mounts will occur is an attacker-controlled directory. Thus the
attacker can first place a symlink to / in their malicious source directory
with the name of a volume, and a subsequent mount in the container will
bind-mount / into the container.
Applying this attack requires the attacker to start containers with a slightly
peculiar volume configuration (though not explicitly malicious-looking such as
bind-mounting / into the container explicitly), and be able to run malicious
code in a container that shares volumes with said volume configuration. It
helps the attacker if the host paths used for volume management are well known,
though this is not a hard requirement.
Workarounds
There are no known workarounds for this issue.
However, users who enforce running containers with more confined security
profiles (such as reduced capabilities, not running code as root in the
container, user namespaces, AppArmor/SELinux, and seccomp) will restrict what
an attacker can do in the case of a container breakout -- we recommend users
make use of strict security profiles if possible (most notably user namespaces
-- which can massively restrict the impact a container breakout can have on the
host system).
References
Credit
Thanks to Etienne Champetier for discovering and disclosing this vulnerability,
to Noah Meyerhans for writing the first draft of this patch, and to Samuel Karp
for testing it.
For more information
If you have any questions or comments about this advisory:
- Open an issue in our issue tracker.
- Email us at [email protected].
Impact
Input manipulates file paths to reach files outside the intended directory, such as configuration or credential files. Typical impact: unauthorized file read or write outside the intended directory.
CVE-2021-30465 has a CVSS score of 7.6 (High). The vector is reachable from an adjacent network, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.0.0-rc95); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
This has been patched in runc 1.0.0-rc95, and users should upgrade as soon as
possible. The patch itself can be found here.
Frequently Asked Questions
- What is CVE-2021-30465? CVE-2021-30465 is a high-severity path traversal vulnerability in github.com/opencontainers/runc (go), affecting versions <= 1.0.0-rc94. It is fixed in 1.0.0-rc95. Input manipulates file paths to reach files outside the intended directory, such as configuration or credential files.
- How severe is CVE-2021-30465? CVE-2021-30465 has a CVSS score of 7.6 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of github.com/opencontainers/runc are affected by CVE-2021-30465? github.com/opencontainers/runc (go) versions <= 1.0.0-rc94 is affected.
- Is there a fix for CVE-2021-30465? Yes. CVE-2021-30465 is fixed in 1.0.0-rc95. Upgrade to this version or later.
- Is CVE-2021-30465 exploitable, and should I be worried? Whether CVE-2021-30465 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2021-30465 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2021-30465? Upgrade
github.com/opencontainers/runcto 1.0.0-rc95 or later.