Docker cp Copy-Out Destination Escape: Understanding the Container File Write Vulnerability

The docker-cp-copyout-destination-escape demonstrates a copy-out destination escape that allows a malicious container process to write files outside the user-specified host destination directory during a docker cp operation.

This vulnerability, documented in the bikini/exploitarium repository, exploits a race condition combined with an unsafe path-prefix validation in Docker's archive extraction logic. Unlike traditional container breakouts, this attack does not escape the container namespace or gain host root privileges, instead escalating the impact of a legitimate host operation to achieve arbitrary file writes on the host filesystem.

What Is the docker cp Copy-Out Destination Escape?

The docker cp copy-out destination escape is a container-to-host file write vulnerability that occurs when a privileged host user copies files from a running container to the host filesystem. According to the source analysis in the bikini/exploitarium repository, the attack allows a process inside the container to redirect the extraction destination to an arbitrary sibling directory on the host L13-L16.

This is classified as a copy-out destination escape rather than a full container breakout because it requires the host user to initiate the docker cp command. The attacker does not gain code execution outside the container or break namespace isolation, but instead manipulates a legitimate host operation to write files to unintended locations L27-L33.

How the Exploit Works

The attack exploits a fundamental weakness in how the Docker CLI validates extraction paths when unpacking tar archives from containers.

The Race Condition

The vulnerability relies on a timing window between the Docker daemon and the container process:

  1. A host user executes docker cp <container>:/tmp/src <host-destination> to copy files from the container
  2. The Docker daemon (in daemon/archive_unix.go) walks the container filesystem and streams a tar archive to the host CLI
  3. Simultaneously, a malicious process inside the container races to create a symlink in the source path
  4. The Docker CLI extracts the archive locally using the vulnerable archive.CopyTo implementation L86-L92

The Path Traversal via Prefix Check

The vulnerable extraction code in cli/command/container/cp.go validates containment using a raw string-prefix check (strings.HasPrefix). When the container creates a symlink whose target path shares the raw prefix of the intended destination, the check incorrectly passes L86-L92.

For example, if the host requests destination /tmp/dst, the container creates a symlink pointing to /tmp/dst2. Since strings.HasPrefix("/tmp/dst2/somefile", "/tmp/dst") returns true, the extraction proceeds into the sibling directory dst2, effectively writing files outside the requested destination L18-L26.

The vulnerable path construction follows this pattern:

// Vulnerable logic in Docker CLI source
targetPath := filepath.Join(filepath.Dir(path), hdr.Linkname)
if !strings.HasPrefix(targetPath, extractDir) {
    // Validation bypassed due to prefix matching
}

Impact and Limitations

This escape represents a specific class of container vulnerability with distinct characteristics that differentiate it from full breakouts.

What It Achieves

  • Container-to-host file write: The attacker can place arbitrary files anywhere the host user has write permissions, provided the target path shares a prefix with the intended destination L49-L54
  • Privilege escalation of host operations: It weaponizes a legitimate administrative action (docker cp) against the host operator
  • Data exfiltration precursor: Written files can establish persistence or prepare for subsequent attacks

What It Does Not Achieve

  • No kernel compromise: This is not a kernel-level memory corruption exploit
  • No guaranteed root access: Success depends on the host user's permissions and the existence of suitable sibling paths
  • No automatic execution: It requires the host user to actively run docker cp against the compromised container L18-L26

Reproducing the Vulnerability

The bikini/exploitarium repository provides a complete proof-of-concept that demonstrates the race condition. To reproduce the escape:


# Clone the repository and navigate to the PoC

git clone https://github.com/bikini/exploitarium.git
cd exploitarium/docker-cp-copyout-destination-escape

# Ensure the script is executable

chmod +x poc.sh

# Execute with a writable host base directory

HOST_BASE=/tmp/docker-cp-copyout-repro ./poc.sh

Successful execution produces output confirming the escape L42-L45:

success=yes
requested_destination=/tmp/docker-cp-copyout-repro/dst
outside_marker_path=/tmp/docker-cp-copyout-repro/dst2/marker
outside_marker_value=container-controlled-host-marker

The poc.sh script launches a container that races the docker cp operation, creating the necessary symlinks to redirect the extraction into the sibling dst2 directory L49-L54.

Mitigation Strategies

To defend against the docker cp copy-out destination escape, implement robust path validation and operational security practices.

Replace prefix checks with boundary validation: The vulnerable strings.HasPrefix validation should be replaced with path-boundary checks that open files relative to a directory file descriptor, ensuring the resolved path remains within the intended extraction root L105-L108.

Operational controls:

  • Avoid running docker cp from untrusted or actively running containers
  • Copy only from stopped containers where filesystem manipulation is impossible
  • Use read-only root filesystems and restricted capabilities to prevent symlink creation in sensitive paths

Summary

  • The docker-cp-copyout-destination-escape is a copy-out destination escape that manipulates the docker cp extraction process to write files outside the intended host directory.
  • The vulnerability exploits a prefix-check bypass (strings.HasPrefix) in the Docker CLI's archive.CopyTo implementation when handling malicious symlinks.
  • This is a container-to-host file write vulnerability, not a full namespace breakout, requiring host user interaction to trigger docker cp.
  • The attack succeeds through a race condition between the daemon's tar stream creation in daemon/archive_unix.go and the container's symlink manipulation.
  • Mitigation requires replacing string-prefix validation with proper path-boundary checks and avoiding copies from untrusted running containers.

Frequently Asked Questions

What type of escape is docker-cp-copyout-destination-escape?

The docker-cp-copyout-destination-escape is a copy-out destination escape or container-to-host file write vulnerability. It allows a process inside a container to write files to arbitrary locations on the host filesystem during a docker cp operation by exploiting a race condition and path validation weakness in the Docker CLI extraction logic.

Does this vulnerability allow full container breakout?

No, this is not a full container breakout. According to the source analysis, the attack does not break out of the container's namespace or gain root privileges on the host. Instead, it escalates the impact of a host-initiated docker cp command to achieve arbitrary file writes wherever the host user has write permissions, making it a limited but serious file-write escape.

What versions of Docker are affected?

The vulnerability exists in the Docker CLI's archive extraction code, specifically in the archive.CopyTo implementation where strings.HasPrefix is used for path validation. While the bikini/exploitarium analysis references the code structure in cli/command/container/cp.go and daemon/archive_unix.go, administrators should consult the official Docker security advisories for specific patched versions and apply updates that implement path-boundary checks rather than prefix validation.

How can I protect against this escape?

Protect against this escape by avoiding docker cp operations from untrusted or running containers, as the attack requires the host user to initiate the copy command. Additionally, implement extraction routines that use directory file descriptors and path-boundary validation instead of naive string-prefix checks, ensuring resolved paths cannot traverse outside the intended destination directory even when symlinks are present.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →