Image Vulnerability Scanning, Dependency Hygiene, Base-Image Maintenance, and Remediation Workflows: Configuration, Design Choices, and Tradeoffs
Choose scanner, policy threshold, rebuild cadence, base-image family, package scope, and exception governance by observable evidence rather than severity screenshots.
Learning objectives
- Compare scanner/tool sources without treating any one database as complete truth.
- Choose fail thresholds and rebuild cadence from risk, ownership, and change-control requirements.
- Distinguish OS-package and language-package findings and connect each to the correct declared source.
- Design accepted-risk exceptions that are digest-bound, owned, justified, and time-bounded.
1. Scanner choice is an evidence-source choice
A scanner is a parser plus inventory engine plus advisory-matching implementation plus policy/reporting surface. Different tools can disagree because they identify packages differently, ingest different advisory feeds, normalize severities differently, or update databases on different schedules. That disagreement is not automatically a bug; it is a signal to inspect package identity and advisory provenance.
The mandatory course path uses Trivy because it is free, local, cross-platform, and can emit machine-readable JSON. Grype is a strong free alternative. Docker Scout is useful when you want Docker-native image analysis, base-image recommendations, policy, and Hub/Desktop integration, but remote repository workflows can introduce account/organization/service boundaries that are not required for this chapter.
2. Decision table: tool and policy choices
| Choice | Strength | Tradeoff / prerequisite | Evidence to preserve |
|---|---|---|---|
| Trivy local | Free local image/file scanning; JSON; broad ecosystems | Needs regularly refreshed databases; output evolves by release | Trivy version, DB metadata, command, JSON, image identity |
| Grype local | Free local scanner; explicit DB status/update controls; Syft ecosystem | Different matching/feeds can differ from Trivy |
Grype version, grype db status, JSON, image
identity
|
| Docker Scout | Docker-native package/CVE/base recommendations and local artifact support | Some repository/dashboard flows require Docker account/org/service enrollment | Scout CLI version, artifact source, image digest, report/policy mode |
| Hard severity gate | Simple automation | Can block on non-applicable/no-fix findings and reward suppression | Threshold, severity source, exceptions, failure output |
| Risk-based gate | Can include reachability/exposure/fixability/business context | Requires governance and consistent ownership | Policy rules, rationale, evidence sources, reviewer |
3. Fail threshold versus risk-based policy
A threshold such as “fail if CRITICAL exists” is easy to automate, but it can conflate severity with exploitability and fixability. A mature policy usually has at least three lanes: immediately actionable findings with fixes; findings needing contextual triage; and accepted exceptions with owner/expiry.
Do not let an exception file become a permanent deny-list of uncomfortable CVEs. The exception must name the exact finding and artifact scope, explain why remediation is not currently possible or proportionate, identify compensating controls where relevant, and expire so the decision is revisited.
4. Rebuild cadence and base-image family
Digest pinning and rebuild cadence solve different problems. A pinned digest gives exact input identity, but it also means you do not automatically receive publisher rebuilds containing fixes. A floating tag can pick up fixes, but it makes rebuilds less reproducible and can introduce breaking change. A controlled workflow pins the reviewed digest, monitors for updated supported bases, then opens a reviewed change that updates the digest and rebuilds.
Base-family choice also affects the advisory model. Alpine, Debian, Ubuntu, Distroless, and language runtime images have different package ecosystems and release/support practices. Do not switch families only to reduce the vulnerability count: compatibility, libc behavior, certificates, timezone data, debugging requirements, and upstream support matter.
5. OS packages versus language packages
An OS-package CVE normally traces to the base image or OS package manager. A language-package finding traces to application dependency metadata such as npm, pip, Maven, Gradle, Go modules, or Cargo. Remediation must reach the source of truth. Updating an OS package cannot fix an npm package, and rebuilding the same lockfile cannot fix a vulnerable language dependency unless an upstream base change happens to alter that package.
When a scanner reports a package, record its ecosystem/source and installed version before deciding which repository/file must change.
6. Freshness is part of correctness
Vulnerability intelligence changes continuously. Trivy downloads vulnerability databases as needed; Grype checks for newer databases and, by default, rejects databases older than its configured maximum age. A report without scanner/database timing is incomplete evidence because you cannot tell whether “no findings” means “no matches in a current database” or “the database was stale.”
In air-gapped environments, mirror and attest database artifacts explicitly. Do not silently turn off freshness validation just to make a pipeline green.
7. Worked scenario: choose a defensible policy
Suppose a release image has: one Critical OS-package finding with a fixed version in a newer supported base; one High language-package finding with no fix; and three Medium findings in packages not used by the application. A defensible approach is to rebuild on the newer reviewed base, update the language dependency when a fix becomes available (or document a bounded exception with exposure analysis), and retain the medium findings in the evidence record rather than hiding them solely because they are inconvenient.
The resulting promotion decision is based on exact image digest + scanner/database identity + fixability + runtime context + owner/expiry, not a single screenshot.
8. Choice checklist
- Can the scanner run on the exact artifact without privileged infrastructure?
- Can you export structured evidence?
- Can you identify database freshness and advisory provenance?
- Does the policy distinguish fixable from non-fixable and owned exceptions?
- Does remediation change declared source and produce a new digest?
- Can you reproduce or explain scanner disagreements?
Knowledge check
Why might Trivy and Grype report different findings for the same image?
They can differ in package discovery, vulnerability feeds, advisory normalization, matching logic, database timing, and severity-source choices. Investigate identity/provenance rather than assuming one is automatically wrong.
Does digest pinning keep a base image patched automatically?
No. Pinning freezes exact bytes. You must monitor for a newer reviewed base digest and update it deliberately.
What source should change for a vulnerable npm dependency?
The application dependency declaration/lockfile, followed by a rebuild. An OS package upgrade is not the correct source-of-truth fix.
What makes a vulnerability exception governable?
Exact artifact/finding scope, owner, rationale, compensating controls where relevant, approval/reviewer, and an expiry or review date.
Why is database freshness an audit field?
Because scan results depend on the advisory snapshot. Without freshness evidence, identical image bytes can appear safer or riskier solely because the database differs.
Official references and version notes
- Docker Engine 29 release notes — current Engine/CLI behavior; Engine 29.8.1 is the current release baseline used in this chapter.
-
Docker build best practices
— rebuild cadence,
--pull, digest pinning, and auditable base-image updates. - Docker Scout quickstart — package/vulnerability analysis and remediation workflow; used here as an optional Docker-native comparison path.
- docker scout cves reference — supported artifact types and local/registry resolution semantics.
- Trivy installation — current free local scanner installation; current documented release is 0.74.0.
- Trivy databases — vulnerability-database retrieval, update controls, and cache behavior.
- Trivy image reference — image scanning, JSON output, severity filters, and fixed/unfixed filtering.
- Grype vulnerability database — database freshness, update behavior, and age validation for the optional Grype path.
- Grype releases — current Grype release evidence; v0.119.0 was released 2026-09-17.
- Alpine release branches — support windows for the exact base-image family used in the disposable lab.
Tool versions are intentionally recorded, not abstracted as “latest”: Trivy 0.74.0 is the current released mandatory scanner baseline and Grype 0.119.0 is the current optional baseline. Docker Scout local analysis and policy capabilities are optional; some remote repository workflows have Docker account/organization boundaries. Policies should bind results to exact image identity/platform and scanner/database evidence, and should never equate “zero findings” with proof of overall security.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.