The Audit Gap
Most Docker security scans check if Privileged: true. If it's false, they move on. The problem: CAP_SYS_ADMIN alone gives containers nearly everything privileged mode does - mount filesystems, manipulate namespaces, potentially escape to the host. And it shows up in audits as just another capability.
In practice: A container running with only --cap-add=SYS_ADMIN can mount the host's /etc directory and read credentials. No privileged flag needed. The container passes every standard check.
This isn't theoretical. FUSE filesystems, monitoring agents, and CI tooling legitimately request SYS_ADMIN. It's in production configs now.
The fix is straightforward:
docker ps -q | xargs docker inspect --format \
'{{.Name}}: Privileged={{.HostConfig.Privileged}} CapAdd={{.HostConfig.CapAdd}}'
Flag anything with SYS_ADMIN, SYS_PTRACE, or SYS_MODULE. Three lines. Run it against production today.
The Escalation Chain
The second pattern is more subtle: two containers that individually pass audits but together enable host access.
Container A: bind mount exposing /etc from the host (read-only, legitimate use case).
Container B: has docker.sock access (common for CI tools, monitoring agents).
Neither alone is the vulnerability. But an attacker controlling Container B can use the Docker API to create a new privileged container mounting the same paths Container A accesses:
docker run --privileged \
-v /etc:/stolen-etc \
-v /var/run/docker.sock:/var/run/docker.sock \
alpine cat /stolen-etc/shadow
The chain: socket access → create privileged container → mount host paths → full credential access.
Context That Matters
Container escapes extend well beyond docker.sock mounting. Recent vulnerabilities (17+ since 2024) include runc flaws like CVE-2024-21626, which leaked host filesystem access, and BuildKit races (CVE-2024-23651/52/53). CVE-2025-9074 in Docker Desktop (patched August 2025) enabled container access to Docker Engine API without socket mounting, allowing host filesystem access on Windows/macOS.
The pattern: neither scenario requires privileged mode, both pass standard checks, and both are active in production environments right now. Runtime monitoring tools like Falco can detect these patterns, but only if configured to look beyond the Privileged boolean.
The real question: how many production containers are running with SYS_ADMIN or docker.sock access because "the monitoring tool needs it" - and nobody remembers why?