Agent Wranglers

INF-74Required

Never give a container control of the host

Never run an app container with --privileged, the host's network or process namespace, or the container engine's socket mounted inside.

How to do it

Each of these hands the container root on the host, so one hole in the app takes the whole machine. If a tool must start containers, such as a CI runner, give it its own machine or a rootless engine. A rootless engine, such as rootless Docker or Podman, runs the engine itself without root, so even an escape lands in an unprivileged user. Add only the one capability the app needs, such as NET_BIND_SERVICE, after dropping all. Set no-new-privileges so a program cannot gain rights through setuid. Keep Docker's default seccomp profile, which blocks about 44 system calls, and never pass seccomp=unconfined. Drop root inside the container too, as Run containers as a user without root says.

Examples

YAML example

services:
  web:
    cap_drop: [ALL]
    security_opt: [no-new-privileges:true]
    # Never add these to an app container:
    # privileged: true
    # security_opt: [seccomp=unconfined]
    # network_mode: host
    # pid: host
    # volumes: [/var/run/docker.sock:/var/run/docker.sock]

How to check

For every running container, docker inspect --format '{{.HostConfig.Privileged}} {{.HostConfig.NetworkMode}} {{.HostConfig.PidMode}} {{.HostConfig.SecurityOpt}} {{json .Mounts}}' shows false, no host, no seccomp=unconfined and no docker.sock.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/infrastructure/containers-and-orchestration/no-privileged-containers">Agent Wranglers infrastructure and environments playbook</a>. In code you write, add a comment next to it with the same link.