# dockerscan

DockerScan is a security scanner for Docker images and containers by Daniel Garcia (cr0hn). It bundles five checks into one binary: CIS Docker Benchmark compliance, supply-chain attack detection, secrets scanning, known-CVE matching, and runtime hardening audit. You point it at an image reference (`dockerscan nginx:latest`) and it pulls the image, runs the enabled scanners, and writes findings as JSON and SARIF plus a color CLI summary.

A note on identity, because the name is misleading. The original dockerscan (v1.x) was a Python offensive toolkit — trojanize images, push/pull/delete against remote registries, discover registries on a network. Version 2 is a full rewrite in Golang and flips the tool from offense to defense: it is now a compliance and vulnerability scanner. The README lists the old offensive and registry features as "preserved… coming soon in v2.1," but they are not in the current tree. What ships today is defensive scanning. If you remember dockerscan as the registry-attack tool, that tool is gone from `master`.

## What it does

The scanners map to five modules, selectable with `--scanners`:

- CIS Docker Benchmark v1.7.0 — 80+ automated controls across host config, daemon hardening, file permissions, image best practices, and runtime.
- Supply-chain detection — patterned on 2024 campaigns: imageless/documentation-only containers, cryptominers, backdoored libraries (the xz-utils/liblzma case), unsigned images (Notary/Cosign), phishing text in image docs, and known-bad network destinations (mining pools, C2, Tor). This overlaps with [[supply-chain-security]].
- Secrets — 40+ patterns (cloud creds, VCS tokens, AI API keys, Stripe/PayPal, DB connection strings, private keys) plus Shannon-entropy analysis for unknown high-entropy strings.
- Vulnerabilities — matches installed packages and Docker itself against a local CVE database, with named coverage of the 2024-2025 container-escape and BuildKit RCE CVEs (CVE-2024-21626 runc, CVE-2024-23651 BuildKit, and others).
- Runtime — audits Linux capabilities (flags CAP_SYS_ADMIN and friends), seccomp, AppArmor/SELinux, namespace isolation, and privileged mode. This is the same threat surface [[sandboxing-ai-agents]] deals with when confining untrusted code, viewed from the container-config side.

## How it works

The layout is a standard Golang CLI: `cmd/dockerscan` is the entry point, `internal/scanner/` holds one subpackage per module behind a shared `Scanner` interface and registry, `internal/report/` has the JSON and SARIF writers, and `pkg/docker/` wraps the Docker client (including credential-helper resolution for private registries — osxkeychain, wincred, pass, and per-registry `credHelpers`). Scanners run concurrently over goroutines. Adding a scanner means embedding `scanner.BaseScanner`, implementing `Scan(ctx, target) ([]Finding, error)`, and registering it.

CVE matching runs against a local SQLite database rather than a live API. A second binary, `nvd2sqlite-cvelistV5`, builds that database from the MITRE cvelistV5 daily snapshot (a single ~525 MB zip from GitHub's CDN — no NVD API key, no rate limits). The default window is the last 30 months, roughly 125,000 CVEs. `dockerscan update-db` downloads the prebuilt database; `--from-file` installs it from disk for air-gapped use. An older `cmd/nvd2sqlite` that used the NVD API 2.0 is deprecated and left only for reference.

Package-to-CVE matching was the weak spot until recently. Versions 2.0.6 and earlier had a query bug that made the package vulnerability check fail and silently discard the error, so every scan reported zero package CVEs regardless of the image. Version 2.1.0 (2026-07-13) rewrote matching around a dpkg-style version comparator with per-(vendor, product) ranges and vendor-verified alias flags. If you pin an older binary, package CVE detection does not work — use 2.1.0 or later.

## Usage

```bash
# Download the CVE database first (updated daily)
dockerscan update-db

# Scan an image with all scanners
dockerscan nginx:latest

# Run only some scanners, write reports to a directory
dockerscan --scanners cis,secrets,supplychain ubuntu:22.04 --output /tmp/reports

# CI mode: quiet banner, exit code drives the pipeline
dockerscan -q myapp:$GITHUB_SHA
```

Exit codes are pipeline-friendly: 0 clean, 1 high-severity findings, 2 critical. SARIF output uploads straight to the GitHub Security tab, GitLab dashboards, or Azure DevOps. Private-registry auth resolves from CLI flags, then `DOCKER_USERNAME`/`DOCKER_PASSWORD` env vars, then `~/.docker/config.json`, and works with Docker Hub, GHCR, ECR, GCR/Artifact Registry, ACR, GitLab, and self-hosted registries.

## Limitations

The license is the main catch. This is not open source — it is a proprietary, source-available license. Free for internal scanning, CI/CD, professional services (consulting, pentesting), education, and research; forbidden without a paid license are offering it as scanning SaaS, selling hosted instances, or building a commercial platform where dockerscan is the primary offering. GitHub reports the license as unrecognized (`NOASSERTION`). Anything beyond internal use needs a read of the LICENSE file.

Other constraints: the CVE database only covers a rolling ~30-month window, so older CVEs are out of scope by design. Vulnerability findings are name-and-version matches against MITRE data, not a full package-manifest scan like Trivy or Grype — name-only matches are flagged but still surface. The tool needs to pull the image (or read a running container), so it is not a static-Dockerfile linter. And the offensive/registry features the README advertises as returning in v2.1 have not landed.

Single-author project (cr0hn), proprietary-licensed, with headline features perpetually "coming soon" — so it is on [[toolbox/watchlist]]. Development is currently active: last commit 2026-07-18, v2.1.0 tagged five days earlier, 92% test coverage claimed. The watchlist entry is about the license and bus-factor risk, not staleness.

Repo: https://github.com/cr0hn/dockerscan — ~1,685 stars, 246 forks, proprietary source-available license.
