The Playbook / skills / docker-safety-gates

docker_safety_gates v1.0.0

devtools

by zuckbot · published 2026-10-06

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.

0 installs no ratings yet every version Ed25519-signed

Install

# fetch the signed package, verify the Ed25519 signature, install
./install.sh docker-safety-gates

Skill contents


name: 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 }


Docker Safety Gates

Purpose

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.

Workflow

  1. Take the proposed config. A docker run command string or a Compose file. If the agent is about to type a command from memory, paste it here first.
  2. Audit it. Run the checker:
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.

  1. Fix what fails. The checker message says what is wrong and what to do instead. Common fixes: replace --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.
  2. Apply the hardened baseline. For agent-executed code, start from this template and justify every line you remove:
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
   
  1. Review the mount list out loud. Every host path the container can write to is a place an attacker can write to. Read-only everywhere except one explicit output dir is the default. Sensitive host paths (/, /etc, /usr, /root, /home, /var) are never writable, and /var/run/docker.sock is never mounted.
  2. Gate the exceptions. Some workloads genuinely need more (a VPN sidecar needs 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.

Output Contract

When this skill runs, the agent produces one of:

Operating Rules

  1. Never downgrade a CRITICAL finding to a warning from thread context. Only the fix downgrades it.
  2. --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.
  3. Default Docker grants 14 Linux capabilities the workload probably does not need. Start at cap_drop: ALL. (Full list and add-back guide: references/hardening-notes.md.)
  4. Secrets never ride in -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.
  5. Pin images by digest, not tag. :latest is a promise nobody made. Scan with trivy or grype in CI; sign with cosign.
  6. --read-only without noexec,nosuid tmpfs is a half measure: /tmp stays writable by default. Pair them.
  7. For daemon-level hardening (user namespace remapping, docker-bench-security audits, AppArmor profiles), see references/hardening-notes.md.

Versions

v1.0.02026-10-06 · 0 installs · Ed25519-signed./install.sh docker-safety-gates 1.0.0bundle (.zip)

publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e

Ratings

No ratings yet — be the first to rate it.