Docker audit fix

How to Audit and Inventory Docker Installations

Docker engine and runc versions come from docker version and runc --version. This baseline check records both, with running and total container counts and the image count, and never fails: a SKIP means the rest of the Docker audit saw nothing either.

Hiren KalariyaLast reviewed: Oct 6, 2026Check docker-inventory
Low
severity
Yes
needs root or sudo
3
results it can return
1 of 8
checks in this audit

Every threshold on this page is transcribed from the docker-security-daemon-socket audit script that CtrlOps runs, and a build check fails if the two ever disagree. See all 8 Daemon & Socket checks, or how the audit runs.

Low severityNeeds sudo

What this check reads

It asks the daemon for its server version with docker version --format '{{.Server.Version}}', takes the runtime version from the first version number in runc --version, and counts lines from docker ps -q, docker ps -aq and docker images -q | sort -u for running containers, total containers and unique images. All of those values go into a single informational PASS line, so there is no threshold and no failing branch. The two SKIPs are the only negative outcomes: no docker binary on the host, or a binary whose daemon could not be reached.

When it applies

Always runs on a host where the docker binary exists; without it, SKIP (noting Podman if that is present instead). Producing the inventory line needs the daemon to be reachable - as root, through sudo, or via docker group membership - otherwise SKIP again. It reports whichever daemon the audit can reach, so on a host running both a rootful and a rootless daemon only one is described. Counts come from docker ps, docker ps -a and docker images, so they reflect that daemon's view at the moment of the audit.

What each result means

Result thresholds this check applies
ResultWhenWhat it means
SKIPDocker not installed (notes Podman if present)Nothing was inventoried, because there is no docker binary here. If Podman is installed the message says so, but nothing in this audit inspects Podman workloads.
SKIPInstalled but daemon unreachableNothing was inventoried. This is the important negative: every other check that needs the daemon will SKIP too, so the Docker audit tells you nothing until access is restored.
PASSInventory lineThe daemon answered and the line records what was found. PASS here means measured, not secure.

Why it matters

You cannot secure a container platform you have not measured. This check is informational - it never fails - and exists to give the rest of the Daemon & Socket script a stated baseline: which engine version is running, which runc is underneath it, and how many containers and images are on the host. It also distinguishes "no Docker findings because Docker is clean" from "no Docker findings because nothing could be inspected", which is the difference between a passing audit and a blind one. NIST SP 800-128 and the CIS benchmarks both begin with inventory for exactly this reason. The engine and runc versions matter directly: container escapes have repeatedly been runc bugs, so the version string here is a vulnerability check in its own right.

Why it fails, and when it is wrong

  • It never returns FAIL or WARN by design. PASS means "this is what was found", not "this is secure".
  • SKIP "daemon not reachable" is the important negative: every other Docker check that needs the daemon will also SKIP, so the whole Docker audit is uninformative until it is fixed.
  • runc --version may be missing from PATH even when containerd bundles it (/usr/bin/runc versus /usr/local/sbin/runc), so runc unknown is cosmetic and does not mean runc is absent.
  • Image and container counts come from the daemon the audit can reach. On a host with both rootful and rootless daemons, only one of them is seen.
  • Podman is reported when Docker is absent, but nothing in this script audits Podman workloads.

How to fix it

Nothing to fix - this check reports, it does not judge. Two things are worth acting on from its output:

  • If it SKIPs, restore daemon access before trusting any other Docker result: start docker.service, grant the audit account sudo or docker group membership, or set DOCKER_HOST for a rootless daemon.
  • Check the versions against known escapes. A runc older than 1.2.8, or a 1.3.x older than 1.3.3, is exposed to three container escapes disclosed in November 2025 (CVE-2025-31133, CVE-2025-52565, CVE-2025-52881). Older releases add CVE-2024-21626 ("Leaky Vessels", container escape via a leaked file descriptor, fixed in 1.1.12) and CVE-2019-5736 (overwriting the host runc binary, 1.0-rc6 and earlier). Upgrade the docker-ce/containerd.io/runc packages rather than only the engine. See the Docker Engine Updates check.

Verify the fix

docker version --format 'engine {{.Server.Version}}'
runc --version
docker ps -q | wc -l; docker ps -aq | wc -l; docker images -q | sort -u | wc -l

# Confirm the versions are not vulnerable to the known escapes:
dpkg -l docker-ce containerd.io runc 2>/dev/null || rpm -q docker-ce containerd.io runc
# runc must be 1.2.8+ or 1.3.3+ (CVE-2025-31133, CVE-2025-52565, CVE-2025-52881)

# If the daemon is unreachable, work out which case you are in:
systemctl is-active docker
id -nG | tr ' ' '\n' | grep -x docker
echo "$DOCKER_HOST"

Debugging

Correct on a host with no Docker. If Podman is in use, note that nothing in this script audits Podman workloads; review them separately.

The single most important failure here, because every other Docker check that needs the daemon will SKIP too. Work through it in order: is the service running (systemctl is-active docker)? can you reach it at all (docker ps)? is the account in the docker group or able to sudo? For a rootless daemon the socket is at $XDG_RUNTIME_DIR/docker.sock and you must set DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock.

Cosmetic: runc is not on the audit's PATH. Find it with find / -name runc -type f 2>/dev/null or docker info | grep -i runc, then check its version manually - it matters, see below.

Check them against the escapes rather than assuming. A runc older than 1.2.8, or a 1.3.x older than 1.3.3, is exploitable through the November 2025 escapes; one before 1.1.12 also through CVE-2024-21626, and 1.0-rc6 or earlier through CVE-2019-5736. Each gives a full container escape regardless of how well the containers are configured.

You are looking at a different daemon (rootful versus rootless), or at a host where another orchestrator manages containers. Compare docker context ls and echo $DOCKER_HOST.

Sources

How the script reads this

Next

Re-run the Daemon & Socket audit after applying the fix and confirm this check moves to PASS. CtrlOps runs all 8 checks over your existing SSH connection and scores the result, so the change is visible without reading another config file.

All 8 Daemon & Socket fixes
Audit your fleet

Find every one of these on every server, in one click

CtrlOps runs this audit over your existing SSH connection - no agents, no scripts to manage. $7/user/month after a 1 month free trial - no credit card required.

Windows

✓ Start instantly·✓ No credit card·✓ No sneaky autorenewals