← Back to Feed CACHED · 2026-07-01 06:55:41 · CACHE_KEY CVE-2026-41579
CVE-2026-41579 · CWE-61 · Disclosed 2026-07-01

runc is a CLI tool for spawning and running containers according to the OCI specification

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A booby-trapped shipping container that can only scratch the paint on the loading dock — not steal the cargo

CVE-2026-41579 is a symlink-following bug in runc's rootfs setup. When runc processes a container image where /dev is a symlink to somewhere else, setupPtmx and setupDevSymlinks naively call os.Remove and os.Symlink against filepath.Join(rootfs, '/dev/ptmx') — which, because filepath.Join resolves symlinks poorly, ends up pointing at a host directory. The attacker gets to delete a file named ptmx in any pre-existing host directory or drop a fixed set of symlinks (fd, stdin, stdout, stderr, core) with hardcoded targets. Affected: runc < 1.3.6, < 1.4.3, < 1.5.0-rc.3.

The vendor's LOW / 3.3 (AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N) is *broadly* correct: no confidentiality loss, no availability loss, no container escape, no code execution — just a narrow integrity primitive exercised by a chosen image at container-start time. But 3.3 undersells the practical picture slightly. Docker masks the flaw with its top-level ro overlay, but Podman and containerd do not, and rootless-Podman users are pulling untrusted images all day. A well-chosen symlink target (e.g. clobbering a systemd unit's ptmx sentinel, or dropping symlinks into a config-scan directory) is a plausible local persistence / tampering primitive. We nudge to MEDIUM (4.5) to reflect the Podman/containerd exposure gap — still nowhere near HIGH.

"Malicious image + Podman/containerd + runc = limited host file damage. Docker users unaffected. Not a container escape."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker publishes malicious OCI image

Adversary crafts an OCI image where /dev is a symbolic link to an absolute host path such as /etc or /var/lib/kubelet. Standard tools (buildah, crane, hand-rolled tar) can produce this — the OCI spec does not forbid it. The image is pushed to a public registry or seeded into an internal mirror.
Conditions required:
  • Attacker can publish or influence an image the victim will pull
  • Victim uses Podman, containerd, CRI-O, or another runc-based runtime that does NOT overlay-mask /dev
Where this breaks in practice:
  • Docker's top-level ro layer masks the malicious /dev symlink — Docker installs are not exploitable
  • Image-signing/cosign policies block unsigned pulls in mature environments
  • Registry allowlists in Kubernetes admission (Kyverno/OPA) can block unknown registries
Detection/coverage: Trivy/Grype/Snyk image scanners flag CVE-2026-41579 by runc version, not image content. Image-content scanners rarely inspect /dev symlinks.
STEP 02

Victim pulls and runs the image on vulnerable runc

A user, CI job, or Kubernetes workload pulls the image and starts a container using an unpatched runc (< 1.3.6 / < 1.4.3 / < 1.5.0-rc.3) under Podman, containerd, or CRI-O. runc create invokes rootfs setup.
Conditions required:
  • User interaction (UI:R) — someone or some automation must run the image
  • Runtime is Podman/containerd/CRI-O with vulnerable runc
Where this breaks in practice:
  • Kubernetes clusters on managed platforms (EKS/GKE/AKS) get runc patched via node AMI refresh within weeks
  • Rootless Podman still runs as the user — host damage limited to what that UID can touch
Detection/coverage: Runtime image-pull audit logs (containerd events, Podman journal) capture the pull but not the exploit primitive.
STEP 03

runc follows /dev symlink during setupPtmx / setupDevSymlinks

setupPtmx calls os.Remove(filepath.Join(rootfs, '/dev/ptmx')). Because /dev inside rootfs is a symlink to e.g. /etc, the resolved path is /etc/ptmx on the host. Any pre-existing host file at that path is deleted. setupDevSymlinks then creates the fixed set of fd/stdin/stdout/stderr/core symlinks in that same host directory.
Conditions required:
  • runc runs with sufficient privilege (root for system Podman/containerd; user UID for rootless)
Where this breaks in practice:
  • Symlink targets and names are hardcoded — attacker can pick the directory but not arbitrary content
  • SELinux/AppArmor container profiles may deny the write when the resolved path crosses the container label
Detection/coverage: auditd -w /etc -p wa catches the host write. Falco rules on open_by_handle_at outside container mount namespace fire.
STEP 04

Attacker leverages the primitive

The realistic payoff: (a) delete a ptmx sentinel file used by a host service, (b) drop symlinks in a directory scanned by a systemd generator, cron, or config-reload watcher to influence host behavior, (c) tamper with monitoring/EDR state files. This is not RCE and not container escape — it is a targeted host-filesystem tamper primitive.
Conditions required:
  • A host process must later read/act on the tampered directory contents
Where this breaks in practice:
  • Fixed symlink names (fd, stdin, stdout, stderr, core) drastically limit which host processes are influenced
  • Most sensitive directories (/etc/shadow, /root/.ssh) do not use those filenames
Detection/coverage: File-integrity monitoring (AIDE, Tripwire, Wazuh FIM) on /etc, /usr/local/etc, /var/lib catches the drop-in.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed as of 2026-07-01. Disclosed same day; no active campaigns.
Proof-of-conceptGHSA-xjvp-4fhw-gc47 advisory includes the technical write-up; no public weaponized PoC repo yet. Trivial to reproduce from the advisory description.
EPSSNot yet scored (disclosure day). Expected <1% — image-borne, requires user pull.
KEV statusNot listed. Unlikely to be added — impact scope too narrow.
CVSSCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N — 3.3 LOW. Local, user interaction required, integrity-only. Vector is accurate.
Affected versionsrunc < 1.3.6, < 1.4.3, and < 1.5.0-rc.3
Fixed versionsrunc 1.3.6, 1.4.3, 1.5.0-rc.3. Debian/Ubuntu/RHEL backports rolling out via runc, containerd.io, podman package channels.
Runtime exposure carve-outDocker: not exploitable (top-level ro layer masks malicious /dev symlink). Podman, containerd, CRI-O: exploitable when using unpatched runc.
Disclosure2026-07-01 via opencontainers/runc GitHub Security Advisory GHSA-xjvp-4fhw-gc47
Reporteropencontainers runc maintainers (Aleksa Sarai and team) — coordinated disclosure via GHSA
04 · The Call

noisgate verdict.

Final Verdict
UPGRADED to MEDIUM (4.5/10)

The decisive factor is impact ceiling: this is a narrow host-filesystem integrity primitive (deleting files named ptmx and dropping a fixed set of symlinks) — not RCE, not container escape, not confidentiality loss. We nudge above the vendor's LOW because Podman and containerd users lack Docker's masking overlay, and container runtimes are canonically high-value-role components — but the primitive itself is too constrained to justify HIGH.

HIGH Affected-version boundaries and Docker carve-out
HIGH Impact ceiling (no RCE, no escape)
MEDIUM Real-world exploitation likelihood under Podman/containerd

Why this verdict

  • Impact is integrity-only and shape-constrained. The primitive is delete-a-file-named-ptmx and drop-a-fixed-set-of-symlinks — attacker picks the directory, not the payload. That is not a general-purpose write.
  • Docker is out of scope. Docker's top-level ro layer masks the malicious /dev symlink. In a fleet where Docker dominates the desktop and CI footprint, exposure is materially smaller than the runc install base suggests.
  • User interaction required. UI:R means someone or something must pull and run the malicious image. Registry allowlists, cosign policy, and Kyverno/OPA admission cut the exposed population further.
  • Role multiplier — container runtime on Kubernetes nodes: the affected component IS a canonical high-value-role component (runs under kubelet/containerd on every worker). Chain succeeds under containerd/CRI-O, but blast radius is capped at *host filesystem tamper*, not node takeover or cluster pivot. That prevents downgrade to LOW but does not lift us to HIGH.
  • Role multiplier — developer workstation with Podman: chain succeeds, blast radius is single-user files. Adds a MEDIUM-amplifier signal, not a floor.

Why not higher?

There is no confidentiality impact, no availability impact, no code execution, and no namespace/cgroup escape. The primitive cannot be turned into RCE without a second, unrelated vuln in a host process that consumes the tampered files. HIGH is reserved for chains that end in host or cluster compromise on their own.

Why not lower?

Vendor LOW (3.3) underweights the Podman/containerd exposure gap and the role-multiplier fact that runc runs on every Kubernetes node. In multi-tenant Kubernetes and shared build environments, a malicious image is a realistic threat model — LOW invites deprioritization past the 1-year mark, which is too long for a runtime component this central.

05 · Compensating Control

What to do — in priority order.

  1. Enforce signed-image admission (cosign + Kyverno/OPA Gatekeeper) — Blocks the delivery vector at the door — malicious untrusted images cannot reach a vulnerable runc. Deploy within the 365-day remediation window; no mitigation SLA applies at MEDIUM, but this control has payoff far beyond this CVE.
  2. Pin container runtime to Docker where feasible on shared multi-tenant hosts — Docker's overlay masks the /dev symlink and makes the flaw unexploitable. Only a valid interim on hosts where Podman/containerd isn't functionally required.
  3. Enable SELinux container_t or AppArmor runc-default profiles in enforcing mode — MAC policy denies the cross-namespace host write even when runc mis-resolves the path. Verify with sestatus / aa-status and audit denials via ausearch -m AVC.
  4. Add auditd + FIM watches on /etc, /usr/local/etc, and container-config directoriesauditd -w /etc -p wa -k runc-symlink plus AIDE/Wazuh FIM catches the primitive if it fires. Detection floor while you roll patched runc.
  5. Roll patched runc (1.3.6 / 1.4.3 / 1.5.0-rc.3) via container runtime package upgrade — Update containerd.io, podman, or vendor node image. Kubernetes node fleets: rebuild AMIs / node images and cordon-drain-replace. Complete within the 365-day noisgate remediation window; prioritize multi-tenant clusters.
What doesn't work
  • Rootless Podman alone — reduces blast radius to the user UID but the primitive still fires; user-writable directories can still be tampered.
  • Network segmentation / WAF / EDR alerting on network traffic — the attack is entirely local to container-start; no network component to inspect.
  • Read-only root filesystem inside the container — the vulnerable operation is runc's setup of the container, before the container's mount is finalized; the container's own ro flag doesn't apply.
  • Seccomp default profiles — the syscalls used (symlink, unlink) are permitted by default profiles because they're required for normal rootfs setup.
06 · Verification

Crowdsourced verification payload.

Run on each Linux host that executes containers (Kubernetes nodes, build agents, developer workstations). Requires read access to the runc binary — no root needed. Invoke as ./check-cve-2026-41579.sh (optionally ./check-cve-2026-41579.sh /usr/local/sbin/runc to override the binary path).

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-41579.sh — detect vulnerable runc versions
# Fixed in: 1.3.6, 1.4.3, 1.5.0-rc.3
# Exit: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u
RUNC_BIN="${1:-$(command -v runc 2>/dev/null)}"

if [ -z "${RUNC_BIN}" ] || [ ! -x "${RUNC_BIN}" ]; then
  # Try common containerd-bundled paths
  for p in /usr/bin/runc /usr/sbin/runc /usr/local/bin/runc /usr/local/sbin/runc /run/torcx/bin/runc; do
    [ -x "$p" ] && RUNC_BIN="$p" && break
  done
fi

if [ -z "${RUNC_BIN}" ] || [ ! -x "${RUNC_BIN}" ]; then
  echo "UNKNOWN: runc binary not found"
  exit 2
fi

RAW=$("${RUNC_BIN}" --version 2>/dev/null | head -n1)
# Expect: 'runc version 1.2.5' or 'runc version 1.5.0-rc.3'
VER=$(echo "${RAW}" | awk '{print $3}')
if [ -z "${VER}" ]; then
  echo "UNKNOWN: could not parse version from: ${RAW}"
  exit 2
fi

# Split into major.minor.patch and optional -rc.N
CORE=${VER%%-*}
SUFFIX=${VER#${CORE}}
IFS='.' read -r MAJ MIN PAT <<< "${CORE}"
MAJ=${MAJ:-0}; MIN=${MIN:-0}; PAT=${PAT:-0}

vuln=1  # assume vulnerable
case "${MAJ}.${MIN}" in
  1.3)
    [ "${PAT}" -ge 6 ] && vuln=0
    ;;
  1.4)
    [ "${PAT}" -ge 3 ] && vuln=0
    ;;
  1.5)
    if [ "${PAT}" -ge 0 ]; then
      # 1.5.0-rc.3 or later is fixed; 1.5.0-rc.1/rc.2 are vulnerable
      if [ -z "${SUFFIX}" ]; then
        vuln=0  # 1.5.0 GA
      else
        RC=$(echo "${SUFFIX}" | sed -n 's/^-rc\.\([0-9]\+\).*/\1/p')
        [ -n "${RC}" ] && [ "${RC}" -ge 3 ] && vuln=0
      fi
    fi
    ;;
  *)
    # 1.6+ or 2.x — assume fixed
    if [ "${MAJ}" -gt 1 ] || { [ "${MAJ}" -eq 1 ] && [ "${MIN}" -gt 5 ]; }; then
      vuln=0
    fi
    ;;
esac

if [ ${vuln} -eq 0 ]; then
  echo "PATCHED: ${RUNC_BIN} version ${VER}"
  exit 0
else
  echo "VULNERABLE: ${RUNC_BIN} version ${VER} — upgrade to 1.3.6 / 1.4.3 / 1.5.0-rc.3+"
  exit 1
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: inventory runc versions across every Kubernetes node, container build host, and developer workstation using the verification script — prioritize hosts running Podman or containerd (Docker-only hosts are not exploitable). This is MEDIUM under the noisgate mitigation SLA, which means *no mitigation SLA applies* — go straight to the noisgate remediation SLA 365-day window, but front-load multi-tenant Kubernetes clusters and shared CI runners inside 90 days because those are the realistic attack surfaces. In parallel, stand up signed-image admission (cosign + Kyverno/OPA) if you don't have it — it's the durable control against image-borne primitives well beyond this CVE. Do NOT drop this to backlog on nodes running containerd/CRI-O with pull-from-public-registry policies.

Sources

  1. GHSA-xjvp-4fhw-gc47 (runc security advisory)
  2. Miggo vulnerability database — CVE-2026-41579
  3. Debian security tracker — CVE-2026-41579
  4. Amazon Linux ALAS — CVE-2026-41579
  5. GitLab advisory database — CVE-2026-41579
  6. OffSeq Threat Radar — CVE-2026-41579
  7. opencontainers/runc releases
  8. Vulnerability-Lookup (CIRCL) — GHSA-XJVP-4FHW-GC47
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.