Skip to content

CVE-2026-41579: Verified Repro With Script Download

CVE-2026-41579: runc symlink deletion via malicious /dev symlink in container image

CVE-2026-41579 is verified against the affected target. This low reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00206.

REPRO-2026-00206 Variant found Jul 2, 2026 CVE entry ↗ .txt
Severity
LOW
CVSS
3.3
Confidence
HIGH
Reproduced in
25m 21s
Tool calls
181
Spend
$2.20
01 · Overview

What Is CVE-2026-41579?

CVE-2026-41579 is a low-severity symlink-following issue (CWE-61) in opencontainers/runc where a malicious container image can trick runc into deleting a host file and creating symlinks on the host during rootfs setup. Pruva reproduced it (reproduction REPRO-2026-00206).

02 · Severity & CVSS

CVE-2026-41579 Severity & CVSS Score

CVE-2026-41579 is rated low severity, with a CVSS base score of 3.3 out of 10.

LOW threat level
3.3 / 10 CVSS base
Weakness CWE-61 (UNIX Symbolic Link Following)

Low — limited impact or hard to exploit. Address in the normal cycle.

How to Reproduce CVE-2026-41579

$ pruva-verify REPRO-2026-00206
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00206/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-41579

Security impact — reproduced
  • reached the target end-to-end
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

container image rootfs where /dev is a symlink to an attacker-controlled host directory

Attack chain
  1. runc run cve-ptmx-test -b /bundle
  2. rootfs /dev setup
  3. setupPtmx/setupDevSymlinks
Variants tested

CVE-2026-41579 can be triggered through runc create+runc start and through a relative /dev symlink in the container image, in addition to the originally reported runc run with an absolute /dev symlink. Both alternate paths reach the same pre-pivot path-based /dev setup sink and are blocked by the fd-based fix in runc…

How the agent worked 480 events · 181 tool calls · 25 min
25 minDuration
181Tool calls
146Reasoning steps
480Events
1Dead-ends
Agent activity over 25 min
Support
31
Hypothesis
2
Repro
189
Judge
21
Variant
233
0:0025:21

Root Cause and Exploit Chain for CVE-2026-41579

Versions: prior to 1.3.6, 1.4.0-rc.1 through 1.4.3, and 1.5.0-rc.1 through 1.5.0-rc.3

CVE-2026-41579 is a low-severity host filesystem integrity issue in opencontainers/runc. When runc prepares a container rootfs, the functions setupPtmx and setupDevSymlinks operate on path strings under the bundle rootfs before pivot_root(2) occurs. If the container image has /dev as a symlink that points outside the rootfs (for example to a host directory controlled by the attacker), filepath.Join(rootfs, "/dev/ptmx") resolves through the symlink and runc deletes or re-creates files on the host. A malicious image can therefore trick runc into removing an existing file named ptmx and creating a small fixed set of device symlinks in an attacker-chosen host directory.

  • Package / component: opencontainers/runc
  • Affected versions: prior to 1.3.6, 1.4.0-rc.1 through 1.4.3, and 1.5.0-rc.1 through 1.5.0-rc.3
  • Risk level: low (per upstream advisory)
  • Consequences: Arbitrary deletion of a host file named ptmx and creation of a limited set of hardcoded symlinks in a host directory reachable via a malicious /dev symlink. Not exploitable under Docker, but exploitable via other runc-based runtimes that do not mask /dev with a top-level read-only layer.

Impact Parity

  • Disclosed / claimed maximum impact: Arbitrary file deletion and symlink creation on the host filesystem through a malicious container image (/dev symlink).
  • Reproduced impact from this run: Vulnerable runc deleted a decoy file named ptmx and replaced it with a symlink in an attacker-controlled directory; fixed runc left the decoy untouched.
  • Parity: full for the documented filesystem-integrity impact. The reproduction does not demonstrate privilege escalation or code execution, which is consistent with the advisory's low-severity rating.

Root Cause

The bug is in runc's rootfs preparation code. Before the container pivots into its rootfs, setupPtmx and setupDevSymlinks use filepath.Join(rootfs, "/dev/...") and then call os.Remove / os.Symlink. Because the operations happen before pivot_root, a /dev entry in the image that is a symlink to an attacker-controlled host directory is followed, causing the operations to affect the host path instead of the container rootfs.

Upstream fix commit:

  • opencontainers/runc@864db8042dbb — "rootfs: make /dev initialisation code fd-based"

The fix rewrites the /dev setup code to operate on file descriptors relative to the opened rootfs directory, so symlinks in the image cannot redirect the operations to host paths.

Reproduction Steps

The reproduction is implemented in bundle/repro/reproduction_steps.sh. At a high level it:

  1. Verifies Docker is available.
  2. Downloads the vulnerable runc release binary (v1.3.5) and the fixed release binary (v1.3.6).
  3. Builds a minimal OCI rootfs from the official busybox image.
  4. Builds two privileged Docker images (repro-runc-vuln and repro-runc-fixed) that each contain one runc binary and the rootfs.
  5. Inside a privileged container, replaces /bundle/rootfs/dev with a symlink to /controlled_dev and creates a decoy /controlled_dev/ptmx.
  6. Generates an OCI bundle with runc spec, disables the terminal, and sets the command to /bin/true.
  7. Runs runc run cve-ptmx-test -b /bundle.
  8. Checks whether the decoy file was deleted.

Expected evidence:

  • Vulnerable (1.3.5): the ptmx decoy is removed and /controlled_dev contains symlinks such as ptmx -> pts/ptmx, core -> /proc/kcore, fd -> /proc/self/fd, etc.
  • Fixed (1.3.6): the ptmx decoy remains untouched and runc does not create host symlinks.

Evidence

  • bundle/logs/repro_vuln.log — vulnerable runc 1.3.5 deletes the decoy and creates host symlinks.
  • bundle/logs/repro_fixed.log — fixed runc 1.3.6 preserves the decoy.
  • bundle/logs/build_repro-runc-vuln.log — Docker build log for the vulnerable image.
  • bundle/logs/build_repro-runc-fixed.log — Docker build log for the fixed image.
  • bundle/repro/runtime_manifest.json — runtime evidence manifest produced by the script.

Key excerpts:

Vulnerable run:

RUN_VERSION: runc version 1.3.5
BEFORE: /controlled_dev/ptmx present?
-rw-r----    1 root     root            10 ... ptmx
...
AFTER: /controlled_dev contents:
-rw-r--r--    ... ptmx
RESULT: decoy deleted

Fixed run:

RUN_VERSION: runc version 1.3.6
BEFORE: /controlled_dev/ptmx present?
-rw-r--r--    ... ptmx
...
AFTER: /controlled_dev contents:
-rw-r--r--    ... ptmx
RESULT: decoy preserved

Recommendations / Next Steps

  • Upgrade runc to a patched version: 1.3.6, 1.4.3, or 1.5.0 (or later).
  • Higher-level runtimes that consume runc should ensure container images cannot ship a /dev symlink that resolves to a host path, or rely on the patched runc version.
  • Regression tests should include a rootfs where /dev is a symlink to a controlled host directory and verify that setupPtmx/setupDevSymlinks do not operate on the host path.

Additional Notes

  • The script is idempotent: it re-downloads only missing binaries, rebuilds the Docker images each run, and uses unique container names.
  • The reproduction uses the real runc CLI binary and the real OCI bundle execution path (runc run), not a reimplemented parser or mocked environment.
  • The Docker-in-Docker privileged container is required in this sandbox because the host environment lacks CAP_SYS_ADMIN and a writable cgroup hierarchy; inside the privileged container runc has the capabilities needed to create a genuine container.
  • No sanitizer or crash is involved; the proof relies on the filesystem state difference between the vulnerable and fixed versions.

Variant Analysis & Alternative Triggers for CVE-2026-41579

Versions: prior to 1.3.6, 1.4.3, and 1.5.0 (as per advisory)

CVE-2026-41579 is a low-severity host filesystem integrity issue in opencontainers/runc. The original reproduction used an absolute /dev symlink in the container image to trick runc into deleting and recreating files on the host before pivot_root(2). This variant stage tested whether the same underlying bug could be triggered through a relative /dev symlink or through the runc create + runc start CLI entry point. Both alternate triggers reproduced the same host-side impact on the vulnerable version (runc 1.3.5), but neither bypassed the fixed version (runc 1.3.6). The upstream fd-based /dev setup also blocks a third candidate, a /dev/pts symlink, because the vulnerable code only touches /dev/ptmx, not /dev/pts itself. No true bypass of the patch was found.

Fix Coverage / Assumptions

The upstream fix (commit a8e53f2c in release-1.3, cherry-picked from 864db8042dbb) rewrites the pre-pivot /dev setup to operate on a pre-opened file descriptor for the real rootfs directory (rootFd). The key assumptions are:

  • rootFd is opened directly on config.Rootfs with O_DIRECTORY|O_CLOEXEC|O_PATH, so it cannot be a symlink.
  • The internal/pathrs helpers (UnlinkInRoot, SymlinkInRoot, MkdirAllParentInRoot) use pathrs-lite / filepath-securejoin to walk paths relative to rootFd without following symlinks that escape the rootfs.
  • All three setup phases (createDevices, setupPtmx, setupDevSymlinks) are now funneled through a single doSetupDev(rootFd, config) call.
  • The same merge also hardens the cgroupv1 merged-subsystem symlink creation (9432ad3a) with pathrs.SymlinkInRoot, covering a sibling path-based symlink operation.

The fix does not change post-pivot_root behavior or other runtime-configured mount paths; it specifically closes the image-controlled /dev symlink path before the container switches root.

Variant / Alternate Trigger

Three distinct candidates were tested:

  1. Relative /dev symlink (/bundle/rootfs/dev -> ../controlled_dev).

    • A different data path from the original absolute symlink. The symlink still resolves to a directory outside the rootfs, so it reaches the same vulnerable sink.
    • Code path: runc run cve-ptmx-test -b /bundleprepareRootfsdoSetupDev(rootFd, config)setupPtmx / setupDevSymlinks.
  2. runc create + runc start entry point.

    • A different CLI invocation that ultimately runs the same prepareRootfs code in the container init.
    • Code path: runc create cve-ptmx-test -b /bundle && runc start cve-ptmx-testprepareRootfsdoSetupDevsetupPtmx / setupDevSymlinks.
  3. /dev/pts symlink (/bundle/rootfs/dev/pts -> /bundle/controlled_dev).

    • A different symlink location inside /dev. The vulnerable setupPtmx only operates on /dev/ptmx, so the /dev/pts symlink does not redirect the host-side file operations. This candidate was ruled out.

Results:

  • Candidates 1 and 2 reproduced on runc 1.3.5 (decoy ptmx file removed and replaced by ptmx -> pts/ptmx plus the hardcoded /dev symlinks).

  • Candidates 1 and 2 did not reproduce on runc 1.3.6; the decoy was preserved.

  • Candidate 3 did not reproduce on either version.

  • Package / component: opencontainers/runc

  • Affected versions: prior to 1.3.6, 1.4.3, and 1.5.0 (as per advisory)

  • Risk level: low (per upstream advisory)

  • Consequences: On the vulnerable version, an attacker-supplied container image with a /dev symlink can cause runc to delete a file named ptmx and create a fixed set of symlinks in an attacker-chosen host directory. The variant triggers demonstrate the same impact through a relative symlink and through the create/start entry point.

Impact Parity

  • Disclosed / claimed maximum impact: Arbitrary deletion of a host ptmx file and creation of a hardcoded set of symlinks in a host directory reachable via a malicious /dev symlink.
  • Reproduced impact from this variant run: On runc 1.3.5, both the relative /dev symlink and the create/start path removed the decoy file and created the expected symlinks in the attacker-controlled directory. On runc 1.3.6, the decoy was preserved in both cases.
  • Parity: full for the documented filesystem-integrity impact. The variants did not demonstrate privilege escalation or code execution, which is consistent with the advisory's low-severity rating.
  • Not demonstrated: A bypass of the fixed version.

Root Cause

The root cause is the same as the original CVE: before the container switches into its rootfs, setupPtmx and setupDevSymlinks used path strings built with filepath.Join(config.Rootfs, "/dev/...") and then called os.Remove / os.Symlink. If the image's /dev is a symlink (absolute or relative) to a directory outside the rootfs, those path operations follow the symlink and affect the host filesystem. The runc create/runc start path reaches the same prepareRootfs code, so the same bug is exercised.

Upstream fix commits:

  • a8e53f2c (release-1.3) / 864db8042dbb (main) — rootfs: make /dev initialisation code fd-based
  • 9432ad3a (release-1.3) / 66acd48f9d42 (main) — rootfs: make cgroupv1 subsystem symlinks fd-based (sibling hardening)
  • d934454bmerge CVE-2026-41579 fixes into release-1.3

Reproduction Steps

The reproduction is implemented in bundle/vuln_variant/reproduction_steps.sh. At a high level it:

  1. Verifies Docker is available.
  2. Downloads the vulnerable runc release binary (v1.3.5) and the fixed release binary (v1.3.6) if not cached.
  3. Builds a minimal OCI rootfs from the official busybox image if not cached.
  4. Builds two privileged Docker images (repro-runc-vuln and repro-runc-fixed) that each contain one runc binary and the rootfs.
  5. For each variant, starts a fresh privileged container and:
    • Generates an OCI bundle with runc spec, disables the terminal, and sets the command to /bin/true.
    • Sets up the variant symlink layout (relative /dev symlink, /dev/pts symlink, or absolute /dev symlink for the create/start entry point).
    • Creates a decoy file named ptmx in the target directory.
    • Runs runc run or runc create/runc start.
    • Inspects whether the decoy was preserved, replaced by a symlink, or deleted.
  6. Compares the vulnerable and fixed results for each variant and exits 1 because no variant bypasses the fixed version.

Expected evidence:

  • Vulnerable (1.3.5): for the relative /dev symlink and the create/start entry point, the decoy ptmx is replaced by a symlink and the target directory contains the hardcoded /dev symlinks (core, fd, stdin, stdout, stderr).
  • Fixed (1.3.6): the decoy ptmx remains a regular file and no new symlinks appear in the target directory.
  • /dev/pts symlink: no version deletes the decoy; the symlink is preserved and /dev/ptmx is created inside the real /dev directory.

Evidence

  • bundle/logs/vuln_variant/relative_dev_symlink_vuln.log — vulnerable runc 1.3.5 replaces the decoy with ptmx -> pts/ptmx and creates the other hardcoded symlinks in the target directory.
  • bundle/logs/vuln_variant/relative_dev_symlink_fixed.log — fixed runc 1.3.6 preserves the decoy.
  • bundle/logs/vuln_variant/create_start_entrypoint_vuln.log — vulnerable runc 1.3.5 reached through runc create/runc start replaces the decoy with symlinks.
  • bundle/logs/vuln_variant/create_start_entrypoint_fixed.log — fixed runc 1.3.6 reached through runc create/runc start preserves the decoy.
  • bundle/logs/vuln_variant/pts_symlink_vuln.log — decoy preserved; /dev/pts symlink is left in place and /dev/ptmx is created in the real /dev directory.
  • bundle/logs/vuln_variant/pts_symlink_fixed.log — same safe behavior on the fixed version.
  • bundle/vuln_variant/runtime_manifest.json — runtime evidence manifest produced by the script.
  • bundle/logs/vuln_variant/fixed_version.txt — exact tested fixed revision.
  • bundle/logs/vuln_variant/vulnerable_version.txt — exact tested vulnerable revision.

Key excerpts:

Relative /dev symlink on vulnerable 1.3.5:

VARIANT: relative_dev_symlink
RUN_VERSION: runc version 1.3.5
BEFORE: /bundle/controlled_dev contents
-rw-r--r--    1 root     root            10 ... ptmx
...
AFTER: /bundle/controlled_dev contents
lrwxrwxrwx    1 root     root            11 ... core -> /proc/kcore
lrwxrwxrwx    1 root     root            13 ... fd -> /proc/self/fd
lrwxrwxrwx    1 root     root             8 ... ptmx -> pts/ptmx
...
RESULT: decoy replaced by symlink

Relative /dev symlink on fixed 1.3.6:

VARIANT: relative_dev_symlink
RUN_VERSION: runc version 1.3.6
BEFORE: /bundle/controlled_dev contents
-rw-r--r--    1 root     root            10 ... ptmx
...
AFTER: /bundle/controlled_dev contents
-rw-r--r--    1 root     root            10 ... ptmx
RESULT: decoy preserved

create/start on vulnerable 1.3.5:

VARIANT: create_start_entrypoint
RUN_VERSION: runc version 1.3.5
RUNC_EXIT: create_rc=0 start_rc=0
AFTER: /bundle/controlled_dev contents
lrwxrwxrwx    1 root     root             8 ... ptmx -> pts/ptmx
...
RESULT: decoy replaced by symlink

create/start on fixed 1.3.6:

VARIANT: create_start_entrypoint
RUN_VERSION: runc version 1.3.6
RUNC_EXIT: create_rc=0 start_rc=0
AFTER: /bundle/controlled_dev contents
-rw-r--r--    1 root     root            10 ... ptmx
RESULT: decoy preserved

Recommendations / Next Steps

  • Upgrade runc to a patched version: 1.3.6, 1.4.3, or 1.5.0 (or later). The 1.3.6 binary was tested here and blocks all variant candidates.
  • Higher-level runtimes should not rely on a /dev symlink in the container image and should verify they are using a patched runc version.
  • Regression tests should include both absolute and relative /dev symlinks, and should exercise both runc run and runc create/runc start.
  • The sibling cgroupv1 symlink fix (9432ad3a) should be kept in any backport; it is part of the same defense-in-depth change.
  • If a future change reintroduces mounting on top of the container root, rootFd must be reopened after that mount, as noted in the prepareRootfs comment.

Additional Notes

  • The script is idempotent: it reuses cached binaries and Docker images, runs each variant in a fresh container, and writes unique log files. It was executed twice and produced the same verdict.
  • File bind-mounts did not work in this Docker environment, so the script generates inner shell scripts on the host and pipes them into the container via sh -s < script. This is documented as the working transport mechanism.
  • The reproduction uses the real runc CLI binary and the real OCI bundle execution path, not a mocked environment.
  • The privileged Docker-in-Docker container is required because the sandbox host lacks CAP_SYS_ADMIN and a writable cgroup hierarchy; inside the privileged container, runc has the capabilities needed to create a real container.
  • No sanitizer or crash is involved; the proof relies on filesystem-state differences between vulnerable and fixed versions.
  • Source identity for the tested binaries is recorded in bundle/vuln_variant/source_identity.json and bundle/logs/vuln_variant/fixed_version.txt / vulnerable_version.txt.

CVE-2026-41579 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:004:34
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · CVE-2026-41579 · REPRO-20
0:03
0:05
web search
0:07
0:08
0:12
0:14
0:15
web search
0:19
0:21
0:27
0:28
web search
0:34
0:35
0:41
0:44
0:50
0:52
1:19
1:19
extract_facts
no facts extracted
1:21
1:21
1:21
supportrepro
4:31
4:33
4:33
4:33
4:34

Artifacts and Evidence for CVE-2026-41579

Scripts, logs, diffs, and output captured during the reproduction.

bundle/ticket.md0.9 KB
bundle/ticket.json1.3 KB
bundle/repro/validation_verdict.json0.7 KB
bundle/repro/runtime_manifest.json0.6 KB
bundle/logs/build_repro-runc-vuln.log1.4 KB
bundle/logs/build_repro-runc-fixed.log1.4 KB
bundle/logs/repro_vuln.log1.0 KB
bundle/logs/repro_fixed.log0.6 KB
bundle/logs/vuln_variant/inner_scripts/relative_dev_symlink_vuln.sh1.8 KB
bundle/logs/vuln_variant/inner_scripts/relative_dev_symlink_fixed.sh1.8 KB
bundle/logs/vuln_variant/inner_scripts/pts_symlink_vuln.sh1.8 KB
bundle/logs/vuln_variant/inner_scripts/pts_symlink_fixed.sh1.8 KB
bundle/logs/vuln_variant/inner_scripts/create_start_entrypoint_vuln.sh1.8 KB
bundle/logs/vuln_variant/inner_scripts/create_start_entrypoint_fixed.sh1.8 KB
bundle/logs/vuln_variant/relative_dev_symlink_vuln.log1.2 KB
bundle/logs/vuln_variant/relative_dev_symlink_fixed.log0.8 KB
bundle/logs/vuln_variant/pts_symlink_vuln.log1.0 KB
bundle/logs/vuln_variant/pts_symlink_fixed.log1.0 KB
bundle/logs/vuln_variant/create_start_entrypoint_vuln.log1.2 KB
bundle/logs/vuln_variant/create_start_entrypoint_fixed.log0.8 KB
bundle/logs/vuln_variant/eval_relative_dev_symlink.txt0.0 KB
bundle/logs/vuln_variant/eval_pts_symlink.txt0.0 KB
bundle/logs/vuln_variant/eval_create_start_entrypoint.txt0.1 KB
bundle/logs/vuln_variant/vulnerable_version.txt0.4 KB
bundle/logs/vuln_variant/fixed_version.txt0.8 KB
bundle/vuln_variant/runtime_manifest.json0.8 KB
bundle/vuln_variant/patch_analysis.md9.4 KB
bundle/vuln_variant/source_identity.json0.9 KB
bundle/vuln_variant/variant_manifest.json3.0 KB
bundle/vuln_variant/validation_verdict.json1.0 KB
bundle/vuln_variant/root_cause_equivalence.json1.8 KB
bundle/repro/reproduction_steps.sh7.5 KB
bundle/repro/rca_report.md5.6 KB
bundle/vuln_variant/reproduction_steps.sh11.8 KB
bundle/vuln_variant/rca_report.md11.2 KB
08 · How to Fix

How to Fix CVE-2026-41579

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-41579 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-41579

How does the CVE-2026-41579 symlink attack work?

A malicious image with /dev symlinked to an attacker-chosen host directory causes runc to delete an existing file named ptmx on the host and create a small, fixed set of device symlinks in that attacker-controlled directory. This is not exploitable under Docker, but affects other container tooling built on runc that does not mask /dev with a top-level read-only layer.

Which runc versions are affected by CVE-2026-41579, and where is it fixed?

Versions prior to 1.3.6, 1.4.0-rc.1 through 1.4.3, and 1.5.0-rc.1 through 1.5.0-rc.3 are affected; it is fixed in 1.3.6, 1.4.3, and 1.5.0.

How severe is CVE-2026-41579?

It is rated low severity per upstream: the impact is limited to arbitrary deletion of a host file named ptmx and creation of a limited, hardcoded set of symlinks in a host directory reachable via the malicious /dev symlink.

How can I reproduce CVE-2026-41579?

Download the verified script from this page and run it in an isolated environment against a vulnerable runc build with a container image whose /dev is a symlink to an attacker-controlled host directory. It shows the vulnerable runc deleting a decoy ptmx file and replacing it with a symlink in that directory, then confirms the fixed build does not.
11 · References

References for CVE-2026-41579

Authoritative sources for CVE-2026-41579 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.