Docker / Supply chain
Don’t Ship What You Haven’t Scanned: Gating Images Before Production
SBOMs, severity gates, workable exceptions, and practical CI steps for container image scanning.
Images move quickly; vulnerability information changes just as quickly. My baseline is straightforward: make image contents visible, scan before release, gate on actionable findings, and define a narrow exception path with an owner and an expiry.
This is not a claim that scanners make an image safe. A scan is one control in a larger process. The goal is to replace last-minute surprises with a repeatable decision before an image reaches production.
Start with an inventory
A Software Bill of Materials (SBOM) lists software components included in an image. Generating one during the build gives scanners and reviewers a concrete inventory to inspect. Docker Buildx can attach an SBOM attestation to an image:
# Build and push to a registry so the SBOM attestation travels with the image.
docker buildx build \
--tag "$IMAGE" \
--sbom=true \
--push .
Build attestations depend on the BuildKit builder and where the image is stored. Verify that the registry contains the SBOM and that your scanner can read it; do not assume a successful command means the inventory is being retained in the place you expect.
Gate on findings the team can act on
Pick a severity policy and make it a failing CI step. For example, Trivy can return a non-zero exit status when High or Critical findings are present:
# IMAGE is the exact tag or digest built by the preceding step.
trivy image \
--exit-code 1 \
--severity HIGH,CRITICAL \
"$IMAGE"
Choose policy with the people who own the service. Severity labels are useful triage signals, but they do not tell you whether a vulnerable code path is reachable in your application. Prioritize fixable findings; keep visibility into the rest and record remediation plans.
Make exceptions narrow and temporary
Sometimes a scanner reports a finding with no available fix, or a team can show that a vulnerable path is not reachable in its deployment. If your policy allows an exception, require at least:
- a named owner responsible for revisiting it;
- a short technical justification and the affected image digest;
- a remediation plan or a reason no fix is available;
- an expiry date that triggers re-review.
An exception should have an end. An expired exception returns to the gate for a fresh decision.
Scan third-party images and every release candidate
Review a base image or build tool before first use, prefer trustworthy publishers, and record the digest of the image you evaluated. Scan the image that will actually be released, not only the Dockerfile or an earlier local build. Repeat the scan when rebuilding because packages and advisories change.
Treat scanner failures as operational failures
Scanning can fail because a registry is unavailable, an advisory feed cannot be fetched, a token expired, or the runner ran out of disk. These states are different from “the scan completed and found a vulnerability.” Preserve enough CI status and logs to tell which happened, and make sure infrastructure errors cannot turn into a silent pass.
Keep the gate fast enough to keep
If every scan takes too long, teams will look for ways around it. Cache what is safe to cache, tune the scanner, and make results easy to understand—but do not quietly skip scanning for small code changes. Also record who approved exceptions and when; keep logs free of credentials and other secrets.
Failure modes to test
- The gate reports but does not block: test the pipeline with a known finding and confirm the build fails.
- Advisory access expires: make registry or scanner authentication failures visible and blocking.
- The SBOM is missing: treat a missing expected artifact as a failed build, not an empty inventory.
- A clean scan becomes stale: rebuild and rescan as dependencies or vulnerability data change.
Try it in your pipeline
- Generate an SBOM for each release image and verify that it is retained.
- Run a vulnerability scan on the exact image tag or digest that will ship.
- Set a failing threshold, such as High and Critical, with a written exception policy.
- Keep scanner outages separate from vulnerability findings in the CI result.
Closing thought
A scan is most useful when it changes a release decision. Make image contents visible, agree on what blocks a release, and give every exception an owner and a clock.