Listen to this Post
How the CVE works (technical)
- When `docker cp` copies data into a container, the daemon builds a temporary filesystem view.
- It bind‑mounts the container’s volumes into a private mount namespace.
- For each volume, the mount destination is resolved inside the container root using
GetResourcePath. - If the destination does not exist, `createIfNotExists` is called to create the mountpoint (a file or directory).
- Between path resolution and the actual creation, a malicious container process can swap a path component with a symlink.
- The symlink points to an arbitrary absolute path on the host filesystem (e.g.,
/etc/docker/daemon.json). - The `createIfNotExists` function uses `os.MkdirAll` and `os.OpenFile` on the already‑resolved absolute path.
- These functions follow symlinks in every intermediate directory component.
- Because the race window is exploited, the symlink is followed outside the container root.
- As a result, an empty file or directory is created on the host filesystem, running with root privileges.
- The temporary mount namespace and the bind‑mount are only torn down after `docker cp` completes.
- However, the newly created empty file/directory persists on the host.
- This is a pure creation primitive – existing host files cannot be overwritten or read.
- The vulnerability requires the container to have at least one volume mount.
- The container process must be able to rapidly create and swap symlinks at the destination path.
- The attack is triggered when an operator runs `docker cp` into the container, or calls the archive API endpoints.
- The flaw is a classic Time‑Of‑Check‑Time‑Of‑Use (TOCTOU) race condition.
- It exists because the daemon trusts the path resolution result after the container has already changed the filesystem.
- The patch introduces `os.Root` (Go 1.24+) which refuses to follow symlinks that escape the opened root directory.
- All filesystem operations are now performed through that `os.Root` handle, confining creations to the container.
dailycve form
Platform: Docker
Version: ≤28.5.2
Vulnerability: Race condition
Severity: High
date: 2026‑05‑18
Prediction: May 18,2026
Analytics under heading What Undercode Say:
Monitor for symlink‑swap attempts inside containers auditctl -a always,exit -F arch=b64 -S symlink,rename -S mkdir -k symlink_race Log all `docker cp` operations docker events --filter event=exec_start --filter type=container | grep -E "docker cp|/archive"
How Exploit:
Inside the malicious container (simplified race loop) while true; do ln -sf /etc/docker/daemon.json /mnt/volume/some/path/target Trigger `docker cp` from outside while this loop runs done The `createIfNotExists` call will then follow the symlink and create an empty directory at `/etc/docker/daemon.json` on the host.
Protection from this CVE
- Upgrade to Docker `v28.5.3` or any version with the
os.Root‑based patch. - Never run `docker cp` against untrusted containers.
- Use an authorization plugin to block `PUT /containers/{id}/archive` and
HEAD /containers/{id}/archive. - Run containers without volume mounts when possible.
Impact
- A malicious container can create empty files/directories anywhere on the host as root.
- Converting `/etc/docker/daemon.json` into a directory prevents the daemon from restarting.
- Creating `/etc/nologin` blocks all user logins on the host.
- Overwriting critical system paths breaks host services (persistent DoS).
- Read/write access to existing host files is not granted – only creation of new empty entries.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

