How to Avoid Exposing the Docker Socket to CI Jobs
Mounting the Docker socket into a job gives that job control of the host daemon, which is equivalent to root on the host.
Access to /var/run/docker.sock lets a job start a privileged container and read the host filesystem. Use per-job Docker-in-Docker or rootless Docker so no shared socket is exposed.
Steps
- Do not add
-v /var/run/docker.sock:/var/run/docker.sockto job containers. - Give each job its own isolated dind sidecar or rootless daemon.
- If a job must build images, prefer a daemonless builder.
Daemonless build instead of socket mount
.github/workflows/ci.yml
steps:
- uses: actions/checkout@v4
# No docker.sock mount; buildkit runs without a shared daemon
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
push: false
tags: myapp:ciGotchas
- A mounted socket lets a job launch
--privilegedcontainers and escape to the host. - Shared dind across jobs re-introduces cross-job contamination; keep it per job.
Related guides
How to Harden Runner Containers Against EscapeReduce container escape risk on self-hosted GitHub Actions runners by running rootless, dropping capabilities…
How to Isolate Self-Hosted Runners Per JobRun each self-hosted GitHub Actions job in its own fresh VM or container with no shared state, so a compromis…