no-broad-bind-mount
Bind-mounting /, $HOME, ~/.ssh, or a parent directory into a Compose service exposes far more of the host than the service needs. Mount the narrowest path, read-only.
On this page
- ~:/home/agent is the fastest way to give a container access to something under your home directory, and it also gives it everything else: SSH keys, cloud credentials, browser profiles, every other project. This rule flags bind mounts whose host source is the root filesystem (/, C:\), the home directory (~, $HOME), a hidden directory under it (~/.ssh, ~/.aws, ~/.docker, …), a parent of the Compose project (../), or a host system directory (/etc, /proc, /run, /home, …). Relative paths inside the project and narrow absolute paths like /opt/models pass. It understands both the short and long volumes syntax and resolves ${VAR:-default} interpolation to its default.
What the rule catches
services:
agent:
image: my-agent:1.2.0
volumes:
- ~:/home/agent
- ~/.aws:/root/.awsScanning this file reports:
⚠ WARN [docker-doctor/no-broad-bind-mount]
Service 'agent' bind-mounts '~', the whole home directory. Everything under it is readable by the container, and a writable mount is the foothold for VM-escape bugs like CVE-2026-77179.Why it matters
A bind mount is a hole in the container boundary by design, and its size is whatever directory you name. Mounting ~ hands over ~/.ssh, ~/.aws, and ~/.docker/config.json, so one compromised dependency in the service becomes a credential theft on the host. The problem got sharper when Docker Desktop and Docker Sandboxes moved to running containers in a VM: the file server for a bind mount runs on the host, and bugs in it turn a writable mount into a full VM escape. CVE-2026-77179 did exactly that with an open file, a deleted directory, and a symlink, all from inside a mounted folder. A VM does not protect the host from a mount it shares with the guest; the only reliable defenses are mounting less and mounting read-only.
How to fix it
Mount the narrowest directory the service actually reads (./data, not ~ or /), and add :ro unless the service must write to it. Host paths the service only needs at build time belong in the image instead.
services:
agent:
image: my-agent:1.2.0
volumes:
- ./workspace:/home/agent/workspace
- ./config/aws:/root/.aws:roTwo things usually fix a broad mount:
- Narrow the source: mount
./dataor/srv/app/uploads, not the directory that happens to contain it. For credentials, copy the one profile the service needs into a project-local directory that is gitignored, or hand the value over as a Composesecretsentry. - Make it read-only: append
:ro(short syntax) or setread_only: true(long syntax). The prefer-read-only-bind-mount rule tracks that half.
Host-monitoring agents (cAdvisor, node exporters) legitimately mount /proc and /sys. Keep those read-only, and set this rule to off in docker-doctor.config.json if the warning is noise in a project dedicated to host monitoring.
The Docker socket is a special case with its own rule, no-docker-socket-mount, and is not reported here.
Rule details
- Rule key —
docker-doctor/no-broad-bind-mount - Category — Compose
- Default severity —
warning - Applies to — Docker Compose files
Explain this rule from the CLI:
npx @docker-doctor/cli@latest rules explain docker-doctor/no-broad-bind-mountChange its severity — or turn it off — in your config file:
// docker-doctor.config.ts
export default {
rules: {
"docker-doctor/no-broad-bind-mount": "off",
},
};Severity affects the health score: error findings cost more points than warning, and info costs the least.