Docker CopyEscape CVE-2026-17106 Lets docker cp Overwrite Host Files
Imperva disclosed CVE-2026-17106 CopyEscape on August 10. Patch Docker Engine 29.7.2 or Desktop 4.86.0 before the next docker cp.
By Dillip Chowdary • Aug 10, 2026 • Source: Imperva Red Team
Imperva Red Team disclosed CVE-2026-17106 on August 10, 2026, a container-to-host arbitrary file-write they named CopyEscape. The bug sits in Docker's docker cp path: a malicious container can turn a routine copy-out into a write on the machine running the Docker CLI. Docker later confirmed the same CVE also affects sbx cp when files leave Docker Sandboxes.
This briefing sticks to what Imperva printed and what Docker shipped. It covers the archive race, the extractor mismatch, who is in the blast radius, and the versions that close it. It does not reproduce the exploit.
What happened
Ron Masas and Imperva reported the finding to Docker on April 11, 2026. Coordinated disclosure slipped past the first 90-day window, then again after the July 30 Engine/CLI 29.7.0 extraction fix caused functional regressions. Docker Desktop 4.86.0, bundling Engine 29.7.2, shipped August 10. Sandboxes 0.38.0 had already patched the sbx cp destination escape on August 6 under the same CVE.
Imperva validated the chain on Linux with Docker Engine 29.6.1 and on macOS with Docker Desktop 4.81.0 (232925). The write runs with the authority of the user or automation that invoked docker cp, not with the privileges of the process inside the container. A public proof-of-concept lives at github.com/masasron/CopyEscape-CVE-2026-17106. The advisory is GHSA-hfg8-hc9c-6c3h on moby/go-archive.
Who is exposed
Anyone who copies files out of a running, untrusted, or already-compromised container onto a sensitive client is in scope. That includes developer laptops using docker cp for logs and artifacts, CI workers that harvest test output, and incident responders who copy evidence from a container they already suspect. AI-agent workflows that use Docker Sandboxes and sbx cp sit in the same class.
The container does not inherit root from dockerd. If an ordinary user runs docker cp, the attacker reaches files that user can write: shell rc files, SSH config, source trees, LaunchAgents on macOS. If an admin, CI image, or maintenance job runs sudo docker cp, the same primitive can replace a root-owned binary. Imperva's Linux demonstration replaced /usr/bin/runc; a later Docker lifecycle step then executed the replacement as root.
Advertisement
Tech Pulse Daily
Get tomorrow's pulse first
Join engineers who read Tech Pulse before stand-up. Free, weekday mornings.
What to do now
Upgrade to Docker Engine and CLI 29.7.2 or later, and Docker Desktop 4.86.0 or later. Sandbox users should be on Docker Sandboxes 0.38.0 or newer. Confirm the version on every builder image and laptop that still runs docker cp, not only on the daemon host you remember.
If you cannot patch today, stop the container before copying — Docker can copy from a stopped container, which blocks the live filesystem race Imperva used. Do not run sudo docker cp. Do not copy out of untrusted or forensic containers onto a production workstation. Pull those artifacts in a disposable VM or throwaway account instead.
How the issue works
docker cp is not a direct filesystem copy. The daemon walks the container's live tree, packs a tar archive, and the CLI extracts that archive on the client. Two properties have to hold: the archive must be coherent, and every extracted object must stay inside the destination the user named. CopyEscape breaks both in one operation.
The producer race is a TOCTOU in moby/go-archive v0.2.0. filepath.WalkDir records an entry as a directory, the container then replaces it with an absolute symlink, and addTarFile emits the symlink. WalkDir still thinks the name is a directory and adds a child under it. The extractor then validates a filepath.Join-constructed targetPath but calls os.Symlink with the original hdr.Linkname. The check approves one path; the kernel creates another. The child entry has no ../, so lexical escape checks pass, and the write lands outside the destination — in Imperva's demo, at /usr/bin/runc.
What is still unknown
Imperva and Docker have not published a count of exploited hosts. The PoC is public, so treat unpatched CI as already reachable. Docker did not assign a second CVE to the source-walk TOCTOU; it was framed as defense-in-depth hardening after the extraction fix. Whether every downstream packager (cloud builder images, GitHub-hosted runners, vendor desktop builds) has rolled 29.7.2 is a local inventory question, not a number in the advisory.
Watch Docker's security advisory and the go-archive changelog for follow-up extractor work. If you brief this to a platform team, lead with the version floor (29.7.2 / Desktop 4.86.0 / Sandboxes 0.38.0) and the rule to stop the container before copy-out. That is the decision. The rest is the primary write-up.
Developer Action Items
- ☐ Inventory whether GitHub / Docker / macOS runs in prod, CI, staging, or on laptops before you debate severity.
- ☐ Pull the vendor advisory for CVE-2026-17106 and patch from that page — not from a social recap.
- ☐ If you cannot patch today, isolate the service, rotate tokens that sat on the affected surface, and raise the logging floor.
- ☐ Record the decision and residual risk so the next on-call does not re-litigate whether you are exposed.
Advertisement