Run untrusted or agent-generated workloads in Docker without the classic footguns. Applies when an agent proposes a `docker run` or Compose config, reviews container security, or needs a hardened one-liner for sandboxed code execution. Ships a static auditor that fails commands with container-escape flags before they run.
./install.sh docker-safety-gatesname: docker_safety_gates description: Run untrusted or agent-generated workloads in Docker without the classic footguns. Applies when an agent proposes a docker run or Compose config, reviews container security, or needs a hardened one-liner for sandboxed code execution. Ships a static auditor that fails commands with container-escape flags before they run. metadata: { risk: low, category: devtools }
An agent that runs Docker containers for untrusted, agent-generated, or third-party code is one flag away from giving that code the whole host. This skill is the gate between the idea and the docker run: a fixed checklist plus a static auditor (bin/docker-run-check.py) that flags escape-grade configurations before anything executes. It advises and audits. It never runs containers itself.
docker run command string or a Compose file. If the agent is about to type a command from memory, paste it here first.bash
python3 bin/docker-run-check.py 'docker run ...' # single command
python3 bin/docker-run-check.py --compose stack.yml # compose file
The checker exits 1 on any CRITICAL finding. A CRITICAL verdict means: do not run, fix first. Warnings are acceptable only when the agent can state why each one is safe for this specific workload.
--privileged with --cap-add for exactly the capability needed (and verify from error logs), swap a docker.sock mount for a read-only socket proxy or TLS-based Docker-in-Docker, remount host paths with :ro.bash
docker run --rm --read-only \
--tmpfs /tmp:size=100m,noexec,nosuid --tmpfs /run:size=10m \
--cap-drop ALL \
--security-opt no-new-privileges:true \
--user 10001:10001 \
--memory 512m --cpus 1 --pids-limit 100 \
--network agent-net \
-v /data/in:ro -v /data/out \
myrepo/app@sha256:<digest>
The Compose equivalent with the same posture:
yaml
services:
agent-runner:
image: myrepo/app@sha256:<digest>
read_only: true
user: "10001:10001"
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
tmpfs: [/tmp:size=100m,noexec,nosuid, /run:size=10m]
deploy:
resources:
limits: {memory: 512m, cpus: "1.0", pids: 100}
networks: [agent-net]
volumes:
- /data/in:/data/in:ro
- /data/out:/data/out
/, /etc, /usr, /root, /home, /var) are never writable, and /var/run/docker.sock is never mounted.NET_ADMIN, a build container may need a writable cache). An exception gets a one-line written justification naming the workload, the flag, and why there is no narrower option. No justification, no flag.When this skill runs, the agent produces one of:
docker run line or Compose snippet starting from the baseline template, pinned to a digest, with every deviation from the template justified.--privileged is never the answer. The answer is the smallest --cap-add that makes the workload start, found by reading the container's permission errors.cap_drop: ALL. (Full list and add-back guide: references/hardening-notes.md.)-e or image layers. They come from a secrets file, a manager, or a mounted tmpfs file. Anything in docker inspect output is public to the host.:latest is a promise nobody made. Scan with trivy or grype in CI; sign with cosign.--read-only without noexec,nosuid tmpfs is a half measure: /tmp stays writable by default. Pair them.references/hardening-notes.md.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.