An SBOM tells you what is in an image. A vulnerability database tells you which of those things has a known problem. Docker Scout joins the two and — the part that makes it useful rather than merely alarming — tells you what to change.
docker scout quickview ghcr.io/acme/app:1.0
This one is a recording — the commands are real, but nothing is running here. Type them into your own shell to follow along.
Three rows, and the third is the one that pays for the tool. Most of your vulnerabilities are in the base image, and most of those are already fixed — the base was rebuilt after you pulled it. Repulling and rebuilding fixes them with no code change at all.
The counts are Critical, High, Medium, Low. Read them relative to each other, not as a score.
docker scout quickview IMAGE # the summary above
docker scout cves IMAGE # every finding, with package and fix version
docker scout recommendations IMAGE # what to change about the base
docker scout compare --to IMAGE-A IMAGE-B # what a change did
docker scout policy IMAGE # evaluate against configured policy
docker scout sbom IMAGE # the inventory itself
cves is the detailed list, and its filters are what make it usable in a pipeline:
docker scout cves --only-severity critical,high ghcr.io/acme/app:1.0
docker scout cves --only-fixed ghcr.io/acme/app:1.0
docker scout cves --format only-packages --only-severity critical ghcr.io/acme/app:1.0
--only-fixed is the filter to reach for first. A finding with no available fix is something to track; a finding with a fix is work you can do this afternoon, and separating the two turns a wall of red into a task list.
Scout reports 40 vulnerabilities, of which 31 are in the base image and already fixed upstream. What is the highest-value action?
Absolute counts are noisy. What matters at review time is whether this change made things worse:
docker scout compare --to ghcr.io/acme/app:main ghcr.io/acme/app:pr-482
This one is a recording — the commands are real, but nothing is running here. Type them into your own shell to follow along.
A reviewer can act on that. "Your branch adds one High by pulling in libxml2, and downgrades openssl" is a specific, arguable claim. "There are 40 vulnerabilities" is not.
docker scout recommendations ghcr.io/acme/app:1.0
This one is about the base image specifically, and it will suggest things like moving node:22 to node:22-alpine, or to a newer patch tag, with the CVE and size deltas each change would produce. It is opinionated in a useful way — the suggestions are ranked by what they remove.
Why is docker scout compare more useful in a pull request than docker scout cves?
Policies turn findings into pass or fail:
docker scout policy ghcr.io/acme/app:1.0 --org acme
Built-in policies cover things like no fixable criticals, no outdated base images, an SBOM being present, no default non-root violation. In GitHub Actions:
- uses: docker/scout-action@v1
with:
command: compare
image: ghcr.io/acme/app:${{ github.sha }}
to: ghcr.io/acme/app:main
only-severities: critical,high
exit-code: true
exit-code: true fails the job. Which is a decision to make deliberately: a gate that fires on findings nobody can fix teaches people to bypass it. Start by gating on fixable criticals introduced by this change and widen once the baseline is clean.
List only the fixable critical and high vulnerabilities in ghcr.io/acme/app:1.0.
A scanner is easy to install and easy to make useless. Four habits separate the two.
Scan the image you ship. Multi-stage builds exist so the compiler is not in production — scanning the build stage reports on software nobody runs and buries the findings that matter.
Fix the base first, and on a schedule. Rebuilding weekly against a refreshed base clears most findings with no code change. This single practice beats any amount of triage, and it is the one people skip because it produces no visible work.
Gate on the delta, not the total. A gate on absolute counts fails on inherited findings and gets bypassed within a fortnight. A gate on newly introduced fixable criticals stays credible, because every failure is something the author can act on.
Record decisions where they are auditable. Findings you accept need a reason attached to the artifact — a VEX statement — not a rule in a scanner's config that nobody revisits.
And use more than one scanner if it matters to you. Scout, Trivy, Grype and Snyk disagree, because they use different databases and different matching rules, and a CVE that one misses is not thereby absent. Scout's advantage is that it is already in the CLI and reads the attestations from the previous lesson directly; that is convenience, not omniscience.
The failure mode to avoid is the one where a scan runs on every build, nobody reads the output, and everyone believes the images are checked. An unread gate is worse than no gate, because it is load-bearing in exactly one place: the conversation after the incident.
Next up: hardened and minimal base images — removing the packages instead of triaging them.
