Proof of concept

Docker cp copy-out sibling-directory escape

A process inside a running container can race a host-initiated docker cp copy-out so that a container-controlled file is written into a host directory next to — but outside of — the destination the operator actually named.

operator asks for/tmp/…/pulled file ends up at/tmp/…/pulled2/marker

What it is

  • An operator-initiated copy-out that escapes the requested destination.
  • A container-controlled write into a sibling host path.
  • A race against archive creation and local extraction.

What it is not

  • Not a no-interaction container breakout.
  • Not a Docker socket / daemon API exposure.
  • Not a guaranteed arbitrary-path write.

Why it works

1. Containment by raw string prefix. The host-side extractor keeps symlink targets "inside" the destination with a string-prefix test. pulled2 passes the check against pulled — it only starts with the same characters, it is not actually inside.

2. The archive is built from the live tree. The daemon walks the container's live filesystem to build the copy-out tar. Swapping a directory leaf into a symlink mid-walk smuggles the symlink and the files beneath it into one tar; extraction writes them through the symlink into the sibling directory.

Reproduce

git clone https://github.com/ajtazer/docker-cp-copyout-sibling-escape
cd docker-cp-copyout-sibling-escape
chmod +x reproduce.sh
WORK_ROOT=/tmp/copyout-escape-repro ./reproduce.sh

A successful run reports success=yes and an escape_marker_path under the sibling pulled2 directory. The race is timing dependent; raise PAD_COUNT on a busy host.

Hardening

View on GitHub Read reproduce.sh