Someone left a trapdoor label on a shipping container, but the forklift ignores it
CVE-2026-79699 is a flaw in the containers/storage Go library — the layer-unpacking engine underneath Podman, Buildah, and Skopeo. A crafted OCI/Docker image layer containing a malicious .wh. (whiteout) header can trick storage/pkg/archive.UnpackLayer, ApplyLayer, or ApplyUncompressedLayer into replacing the extraction destination directory with an attacker-controlled file. Affected library versions: all releases of github.com/containers/storage, and go.podman.io/storage before 1.62.1 (1.62.x branch) and before 1.64.1 (1.64.x branch). Downstream consumers include Podman (fixed in v5.8.7 and v6.1.2), Buildah, Skopeo, RHEL 8/9/10, OpenShift Container Platform 4, Red Hat Quay 3, and Azure Linux 3.
Red Hat rates this MEDIUM 4.4 (CVSS:3.1) while the GitHub Security Advisory (GHSA-mmq6-9mjh-hvq3) scores it Moderate 6.1 — the disagreement hinges on whether integrity impact is Low or High. Crucially, the Podman maintainers added an explicit caveat in the v5.8.7 and v6.1.2 release notes: *"we do not believe these CVEs are exploitable through the Podman command line."* That statement, combined with zero public PoCs and an EPSS of 0.13%, tells us the vendor severity already overstates real-world risk. The bug is academically interesting — whiteout handling is subtle — but requires a victim to pull a malicious image and hit a code path that the primary consumer (Podman) cannot even reach.
4 steps from start to impact.
Craft malicious OCI layer
.wh. prefix) with a path-traversal payload that references the extraction destination directory itself. This layer is embedded in a container image and pushed to a registry the victim will pull from. Tools like tar and crane can assemble arbitrary layer content.- Attacker can publish to a container registry the victim trusts or browses
- Most enterprises pull from curated internal registries, not arbitrary public repos
- Registry scanning (Trivy, Clair, Quay security scanning) inspects layer content pre-pull
Victim pulls the malicious image
podman pull, buildah from, or skopeo copy referencing the attacker's image. The containers/storage library begins extracting layers via UnpackLayer or ApplyLayer.- Victim runs Podman < 5.8.7 / < 6.1.2, or an unpatched Buildah/Skopeo version
- Victim explicitly pulls the malicious image tag or digest
- Podman maintainers state this code path is not reachable through the Podman CLI — the vulnerable branch requires a specific internal API invocation pattern
- Buildah and Skopeo *may* reach the path, but no researcher has demonstrated it
- Image pull is an interactive decision; automated pipelines pin digests
Whiteout header replaces extraction directory
.wh. entry causes the library to replace the extraction destination directory with an attacker-supplied file. This is a local file-overwrite primitive constrained to the storage root (typically /var/lib/containers/storage). The overwrite affects integrity of the local layer store, not arbitrary host paths.- The vulnerable
UnpackLayer/ApplyLayercode path is actually reached (disputed by vendor) - Process has write access to the container storage directory
- Overwrite is scoped to the container storage root — not arbitrary filesystem paths
- On rootless Podman, the storage root is inside
$HOME/.local/share/containerswith user-level privileges only - SELinux
container_var_lib_tlabels prevent writes outside the storage tree
/var/lib/containers/storage would flag unexpected overwrites. Audit logs capture file operations under the storage directory.Attacker leverages overwritten file
podman build or buildah commit. The realistic outcome is denial of service (corrupted storage) rather than code execution.- The overwritten file must be in a location that influences a subsequent privileged operation
- A privileged process must consume the corrupted file without validation
- No demonstrated path from file overwrite to code execution
- Corrupted storage typically causes build failures, not exploitation — the blast radius is self-limiting
- Container storage is ephemeral and frequently recreated
The supporting signals.
| In-the-wild exploitation | None observed. Not listed in CISA KEV. No campaigns, ransomware, or threat-actor usage reported as of 2026-09-23. |
|---|---|
| Proof of concept | No public PoC. GHSA-mmq6-9mjh-hvq3 credits Arpit Jain (@arpitjain099) as the reporter. No exploit code published. Podman maintainers explicitly state the flaw is not exploitable through the CLI. |
| EPSS | 0.0013 (0.13% probability of exploitation in 30 days, 3rd percentile) — bottom of the distribution. |
| KEV status | Not listed. No CISA due date. |
| CVSS interpretation | Red Hat: 4.4 (AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:L). GHSA: 6.1 (AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:L). Disagreement on integrity impact (L vs H). Local-only, requires user interaction, no confidentiality impact. Neither vector reaches network-reachable. |
| Affected versions | go.podman.io/storage < 1.62.1 and ≥ 1.63.0 < 1.64.1. Legacy github.com/containers/storage — all versions (vendor advises migration). Downstream: Podman < 5.8.7 / < 6.1.2, RHEL 8/9/10, OCP 4, Quay 3, Azure Linux 3 (skopeo ≤ 1.14.4-12). |
| Fixed versions | go.podman.io/storage 1.62.1 and 1.64.1 (commit 67d3951). Podman v5.8.7 (5.x LTS) and v6.1.2 (6.x). RHEL/OCP errata pending. Debian: no fix published yet. |
| Exposure surface | Not network-exploitable. No Shodan/GreyNoise/Censys signal — this is a local library flaw, not a listening service. Exposure is governed by who pulls untrusted container images on unpatched hosts. |
| Disclosure timeline | Reported 2026-08-25 → Published 2026-09-15 → Podman patches released 2026-09-16 (next-day turnaround). |
| Reporter | Arpit Jain (@arpitjain099), security researcher. Contributed to Anchore/Grype and other container-security projects. |
Why this verdict
- Vendor non-exploitability statement: The Podman maintainers — who *wrote* the affected code — explicitly state in the v5.8.7 and v6.1.2 release notes that they "do not believe these CVEs are exploitable through the Podman command line." When the upstream author says the primary consumer can't reach the vulnerable path, that is the strongest possible friction signal.
- No PoC, no exploitation, basement-tier EPSS: Zero public exploit code, zero in-the-wild activity, EPSS at the 3rd percentile (0.13%). The vulnerability was disclosed a week ago with a same-day patch; if it were easily weaponizable, researchers would have a PoC by now.
- Local-only, user-interaction-required, scoped overwrite: CVSS
AV:L/UI:Rmeans an attacker cannot reach this remotely. The victim must actively pull a malicious image. The overwrite is constrained to the container storage directory, not arbitrary host filesystem paths. On rootless Podman the blast radius is a user-owned directory. - Role multiplier — CI/CD (Buildah): Buildah in CI/CD pipelines is the most plausible high-value-role consumer. In theory, a supply-chain attack via a poisoned base image could hit the vulnerable
UnpackLayerpath duringbuildah from. However: (a) the vendor has not confirmed Buildah CLI is reachable either, (b) overwrite is scoped to the storage root, not build output, (c) CI pipelines that pin image digests and use internal registries are not reachable. The chain does not succeed with domain/fleet/supply-chain blast radius — at worst it corrupts a build worker's local storage (host-level). This does not trigger the HIGH floor. - Role multiplier — OpenShift/CRI-O nodes: OCP nodes use CRI-O, which also links containers/storage. But CRI-O's image-pull path goes through different extraction code and is subject to cluster-level image policies. No evidence this path is reachable in CRI-O. Host-level blast radius at most; does not reach fleet-scale.
- GHSA vs Red Hat scoring discrepancy: GHSA rates integrity as High (6.1) while Red Hat rates it Low (4.4). Red Hat's assessment — from the team that maintains the code — is more credible. The overwrite replaces the *extraction directory*, not arbitrary filesystem locations. I:L is correct.
Why not higher?
The only path to MEDIUM or above would require a demonstrated PoC showing exploitation through a real CLI tool (Podman, Buildah, or Skopeo) with impact beyond the container storage directory — such as arbitrary host file overwrite or code execution. None of that exists. The vendor's own "not exploitable through CLI" statement, combined with EPSS at the 3rd percentile and zero exploitation evidence, makes even MEDIUM unsupportable. The CI/CD supply-chain scenario is theoretical and unvalidated.
Why not lower?
IGNORE would be appropriate only if the flaw were entirely non-exploitable or affected dead code. The vulnerable functions (UnpackLayer, ApplyLayer) are real, actively used code paths in a widely-deployed library. A fix was committed and shipped within 24 hours of disclosure, which means the maintainers took it seriously enough to patch. The library is embedded in RHEL, OCP, and every Podman installation — the installed base is enormous even if exploitability is low. This warrants tracking and eventual patching, not outright dismissal.
What to do — in priority order.
- Update containers/storage to ≥ 1.62.1 or ≥ 1.64.1 — The definitive fix. Per the noisgate remediation SLA for LOW, treat this as backlog hygiene — no hard deadline, but roll it into your next scheduled container-tooling update cycle. Podman v5.8.7 / v6.1.2 bundle the fix.
- Pin container image references to digests in CI/CD pipelines — Prevents substitution attacks where an attacker pushes a malicious tag. Use
image@sha256:...instead ofimage:latest. This eliminates the supply-chain delivery vector entirely. - Restrict registry sources to internal mirrors — Configure Podman/Buildah
registries.confto only pull from vetted internal registries. Blocks the attacker's ability to serve a malicious image to your fleet. - Enable container image scanning in CI — Run Trivy, Grype, or Clair on every pulled image. Layer-level scanning can flag anomalous whiteout entries and known CVEs in base images before they reach build workers.
- Run Podman/Buildah rootless where possible — Rootless mode constrains the storage directory to
$HOME/.local/share/containers, limiting any file-overwrite impact to user-owned paths. Combined with SELinux, this makes host-level impact negligible.
- Network segmentation / firewall rules — This is a local library flaw triggered by image content, not a network service. Firewalling does nothing to prevent exploitation.
- WAF or IDS/IPS — No network traffic signature to match. The malicious payload is inside a container image layer (tar archive), not an HTTP request.
- Disabling whiteout processing — There is no configuration knob in containers/storage to disable whiteout handling. Whiteouts are a fundamental part of overlay filesystem semantics; disabling them would break all multi-layer images.
Crowdsourced verification payload.
Run on each container host or CI build worker where Podman, Buildah, or Skopeo is installed. Requires read access to the Go module cache or the installed binary. Example: sudo bash check_cve_2026_79699.sh
#!/usr/bin/env bash
# CVE-2026-79699 checker — containers/storage whiteout directory replacement
# Run on hosts with Podman, Buildah, or Skopeo installed.
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
RESULT="UNKNOWN"
check_version() {
local tool="$1"
local ver
ver=$("$tool" --version 2>/dev/null | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1) || return 1
echo "[*] Found $tool version: $ver"
echo "$ver"
}
version_gte() {
# Returns 0 if $1 >= $2
printf '%s\n%s' "$2" "$1" | sort -V -C
}
# Check Podman
if command -v podman &>/dev/null; then
PODMAN_VER=$(check_version podman)
if [ -n "$PODMAN_VER" ]; then
MAJOR=$(echo "$PODMAN_VER" | cut -d. -f1)
if [ "$MAJOR" -eq 5 ]; then
if version_gte "$PODMAN_VER" "5.8.7"; then
echo "[+] Podman $PODMAN_VER >= 5.8.7 — PATCHED"
RESULT="PATCHED"
else
echo "[-] Podman $PODMAN_VER < 5.8.7 — VULNERABLE"
RESULT="VULNERABLE"
fi
elif [ "$MAJOR" -ge 6 ]; then
if version_gte "$PODMAN_VER" "6.1.2"; then
echo "[+] Podman $PODMAN_VER >= 6.1.2 — PATCHED"
RESULT="PATCHED"
else
echo "[-] Podman $PODMAN_VER < 6.1.2 — VULNERABLE"
RESULT="VULNERABLE"
fi
elif [ "$MAJOR" -le 4 ]; then
echo "[-] Podman $PODMAN_VER (v4.x or older) — VULNERABLE (EOL branch)"
RESULT="VULNERABLE"
fi
fi
fi
# Check Buildah
if command -v buildah &>/dev/null; then
BUILDAH_VER=$(check_version buildah)
if [ -n "$BUILDAH_VER" ]; then
echo "[*] Buildah $BUILDAH_VER detected — cross-reference with go.podman.io/storage version"
# Buildah doesn't directly expose storage lib version; flag if Podman wasn't found
if [ "$RESULT" = "UNKNOWN" ]; then
echo "[!] Cannot determine patch status from Buildah version alone."
echo "[!] Check: go list -m go.podman.io/storage 2>/dev/null in the build environment."
fi
fi
fi
# Check Skopeo
if command -v skopeo &>/dev/null; then
SKOPEO_VER=$(check_version skopeo)
if [ -n "$SKOPEO_VER" ]; then
echo "[*] Skopeo $SKOPEO_VER detected — cross-reference with go.podman.io/storage version"
fi
fi
# Try to check the Go module directly if available
if command -v go &>/dev/null; then
STORAGE_VER=$(go list -m -json go.podman.io/storage 2>/dev/null | grep -oP '"Version":\s*"v?\K[0-9.]+' || true)
if [ -n "$STORAGE_VER" ]; then
echo "[*] go.podman.io/storage module version: $STORAGE_VER"
if version_gte "$STORAGE_VER" "1.64.1"; then
echo "[+] storage >= 1.64.1 — PATCHED"
RESULT="PATCHED"
elif version_gte "$STORAGE_VER" "1.63.0"; then
echo "[-] storage >= 1.63.0 but < 1.64.1 — VULNERABLE"
RESULT="VULNERABLE"
elif version_gte "$STORAGE_VER" "1.62.1"; then
echo "[+] storage >= 1.62.1 (1.62.x branch) — PATCHED"
RESULT="PATCHED"
else
echo "[-] storage < 1.62.1 — VULNERABLE"
RESULT="VULNERABLE"
fi
fi
fi
if ! command -v podman &>/dev/null && ! command -v buildah &>/dev/null && ! command -v skopeo &>/dev/null; then
echo "[*] No Podman/Buildah/Skopeo found — not affected."
RESULT="PATCHED"
fi
echo ""
echo "=== CVE-2026-79699 STATUS: $RESULT ==="
case "$RESULT" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esacWhat defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.