Container Image Security Review Checklist
Container image review follows artifact from source to runtime. Tags are mutable labels; digest identifies exact content. Docker documents that digest pinning makes builds repeatable, but pinned bases need deliberate updates when upstream fixes arrive. Review build and runtime policy together; neither replaces registry, host, or cluster assessment.
Buyer evidence pack
Request Dockerfile, .dockerignore, build log, SBOM or package inventory, scan output tied to digest, registry metadata, deployment manifest, and exception register. Every artifact needs repository, commit, digest, timestamp, owner, pass/fail, and storage location. A scan without a digest cannot prove which image was assessed.
| Gate | Evidence | Pass condition | Owner |
|---|---|---|---|
| Provenance | registry, source commit, digest | digest resolves to reviewed build | build owner |
| Layers | history and SBOM | no secret or unneeded artifact | application owner |
| Base | source, tag, digest, refresh record | supported source; update path exists | platform owner |
| Runtime user | Dockerfile and Pod settings | named non-root UID where possible | workload owner |
| Runtime policy | manifest and admission result | policy decision retained | cluster owner |
Build and layers
Use multi-stage builds so compilers, test fixtures, package caches, and source maps do not enter final image unless needed. Docker recommends trusted small bases and only runtime dependencies. Inspect every COPY, ADD, RUN, ENV, and build argument. A secret removed in a later layer remains in earlier layer history. Do not put long-lived credentials in Dockerfile instructions, environment layers, source, or broad build context. Exclude local environment files, keys, dependency caches, and unused tests with .dockerignore.
FROM alpine:3.21@sha256:<reviewed-digest>
RUN addgroup -S app && adduser -S -G app -u 10001 app
WORKDIR /app
COPY --chown=10001:10001 --from=build /out/server ./server
USER 10001:10001
ENTRYPOINT ["./server"]
Replace placeholder during approved build; it is not production value. Record resulting digest and source revision. Pinning controls artifact identity, not vulnerability status. Rebuild with --pull when policy permits a base refresh, scan new digest, review delta, and promote approved output only.
Package triage
Compare inventory with application need. Shells, package managers, compilers, debugging tools, and unused certificates add components to inspect. Small image does not mean secure. Validate executable ownership, writable paths, exposed ports, default command, and remote fetches. Use explicit COPY rather than copying whole context.
Scan findings require triage, not automatic acceptance or rejection. Record package, installed version, digest, fix availability, exposure, owner, decision, and due date. Pass only when policy is met or time-bounded exception names approver and compensating control. Suppression without expiry fails review. Completed remediation needs new digest, revised scan, and rechecked deployment reference.
Runtime policy
Kubernetes workload should use approved digest and restrictive settings when application supports them:
securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: ["ALL"] }
Test startup, logging, temporary files, and ownership; read-only root often needs explicit writable volume. Admission policy may reject mutable tags, privileged containers, root users, or unscanned digests. Save policy decision with manifest. Exception requires workload, reason, owner, compensating control, expiry, remediation, and retest result.
Release decision record
Before release, join source revision, image digest, SBOM, scan, admission result, and deployment manifest in one immutable release record. Record decision owner, decision time, environment, policy version, and whether all gates passed. Preserve registry retention and rollback digest too, so incident responders can identify and restore known output. A failed gate stays failed until a replacement digest supplies evidence; rebuilding same tag without recording its digest is not remediation. For emergency promotion, retain explicit exception and schedule normal review after containment.
Deliverable and boundary
Deliver digest register, evidence index, layer/package findings, runtime-policy result, exceptions, and remediation owner/status. Image review cannot prove a running workload has no exploit path. Infrastructure testing can inspect agreed deployment scope.
Worked case: rebuild from approved base
Build one service image from pinned approved base, capture digest, software inventory, and scanner output. Expected deployment admission references immutable digest, not mutable tag. Introduce a known policy-violating package only in test branch; pipeline should block promotion with finding tied to layer or package, while normal image proceeds through documented exception-free path. Rebuild later from same inputs and compare expected reproducibility signals without claiming bit-for-bit identity unless build system guarantees it.
Test revoked registry credential, unsigned image where signature policy applies, stale vulnerability feed, and image replacement after scan. Closure evidence contains build run, digest, inventory, scanner timestamp and database version, admission result, remediation owner, and retest. An exception must bind to digest or narrowly defined package, set expiry, and require independent confirmation that replacement image is scanned before expiry.
Operational handoff: release owner maps deployed digest to build record and environment. Registry retention preserves digest for incident response. Test rollback with prior approved digest, then rescan if policy or feed changed. Record output with release evidence.
Before promotion, platform owner confirms runtime pulls exact approved digest. Test registry outage and revoked pull authorization in non-production path; output must fail closed under declared deployment policy. Link test result to image release record.