Most container risk is decided before a container ever runs. The base image you choose, the packages you add, and whether anyone rebuilds the image when new CVEs land determine the attack surface you ship.
This guide covers docker image security end to end: choosing minimal base images, writing safer Dockerfiles, scanning in CI, generating SBOMs, signing images and enforcing policy at deploy time.
Each section includes commands you can adapt. Tools named are common open-source options; equivalent commercial products work the same way.
A general-purpose base image brings a full userland: shells, package managers, compilers and hundreds of libraries your application never calls.
Every one of them can carry CVEs, and every one is a tool an attacker can use after initial access.
The data supports caution. Sysdig’s 2023 Cloud-Native Security and Usage Report found that 87% of container images had high or critical vulnerabilities, but only 15% of fixable critical and high vulnerabilities were in packages actually loaded at runtime (2023).
That gap is the argument for smaller images: if a package is not present, its CVEs cannot be exploited and do not need triage.
Leaving known weaknesses unresolved also has a compounding cost. Old images drift further from patched upstream versions, and a rebuild that would have been trivial becomes a breaking upgrade.
NIST’s SP 800-190 Application Container Security Guide lists image vulnerabilities, embedded secrets and use of untrusted images among the primary container risks.
Outdated packages are only one path. Public registries have also been used to deliver malicious content directly:
In ATT&CK terms these map to T1195.002 (Compromise Software Supply Chain) and T1610 (Deploy Container), with T1611 (Escape to Host) as the follow-on risk when a container runs privileged.
Kernel and runtime flaws remain relevant too; a container breakout vulnerability turns any foothold in an image into host access.
| Base type | Examples | Strengths | Trade-offs |
|---|---|---|---|
| Full distribution | ubuntu, debian | Familiar tooling, easy debugging | Largest attack surface and CVE count |
| Slim variants | debian-slim, python:3.x-slim | Fewer packages, same libc | Still includes shell and package manager |
| Alpine | alpine | Very small | musl libc can cause compatibility issues |
| Distroless | gcr.io/distroless/static, /base | No shell or package manager | Debugging needs ephemeral debug containers |
| Hardened low-CVE images | Vendor-maintained minimal images | Rebuilt continuously, often with SLAs | Vendor dependency, possible cost |
Hardened image providers rebuild packages from source to keep CVE counts down; Minimus describes this approach to near zero CVE images.
Whichever route you take, the principle matches CIS Controls v8 Control 2 (inventory and control of software assets) and Control 7 (continuous vulnerability management): ship only what you need and know exactly what that is.
A multi-stage build keeps compilers and build tools out of the final image. The example below builds a Go service and ships it on a distroless base as a non-root user.
# syntax=docker/dockerfile:1
FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags=”-s -w” -o /out/app ./cmd/app
# Pin by digest, not just tag
FROM gcr.io/distroless/static-debian12@sha256:<digest>
COPY –from=build /out/app /app
USER 65532:65532
ENTRYPOINT [“/app”]
Scan every image at build time, fail the pipeline on findings that matter, and rescan stored images daily because new CVEs are published against old packages. Trivy and Grype are widely used open-source scanners.
# Scan a local image and fail on fixable high/critical CVEs
trivy image –severity HIGH,CRITICAL –ignore-unfixed –exit-code 1 myapp:1.4.2
# Equivalent with Grype
grype myapp:1.4.2 –fail-on high –only-fixed
# Scan the Dockerfile and IaC for misconfigurations
trivy config –exit-code 1 ./
The workflow below is illustrative. Pin third-party actions to full commit SHAs, not tags; security tooling itself has been targeted in supply chain attacks.
jobs:
build-scan:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # for keyless signing
packages: write
steps:
– uses: actions/checkout@<commit-sha>
– name: Build
run: docker build -t ghcr.io/org/myapp:${{ github.sha }} .
– name: Scan
run: trivy image –severity HIGH,CRITICAL –ignore-unfixed –exit-code 1 ghcr.io/org/myapp:${{ github.sha }}
– name: SBOM
run: syft ghcr.io/org/myapp:${{ github.sha }} -o spdx-json > sbom.spdx.json
– name: Push and sign
run: |
docker push ghcr.io/org/myapp:${{ github.sha }}
cosign sign –yes ghcr.io/org/myapp@$(docker inspect –format='{{index .RepoDigests 0}}’ ghcr.io/org/myapp:${{ github.sha }} | cut -d@ -f2)
cosign attest –yes –type spdxjson –predicate sbom.spdx.json ghcr.io/org/myapp:${{ github.sha }}
For a comparison of scanners and runtime tools, see the best container security tools roundup.
A software bill of materials lists every package and version in an image. When the next XZ-style incident hits, an SBOM index answers “where do we run this?” in minutes instead of days.
CISA’s 2025 Minimum Elements for a Software Bill of Materials sets out the fields an SBOM should contain.
# Generate SPDX and CycloneDX SBOMs
syft myapp:1.4.2 -o spdx-json=sbom.spdx.json -o cyclonedx-json=sbom.cdx.json
# Scan an SBOM later without pulling the image
grype sbom:./sbom.cdx.json
Store SBOMs as signed attestations next to the image in the registry, then feed them into a dependency inventory so you can query across all deployed images.
Scanning in CI only helps if production refuses images that skipped the pipeline. Sign images with Sigstore cosign, then verify signatures and attestations at admission.
# Verify a keyless signature from a specific CI identity
cosign verify ghcr.io/org/myapp@sha256:<digest> \
–certificate-identity-regexp “https://github.com/org/myapp/.github/workflows/.*” \
–certificate-oidc-issuer https://token.actions.githubusercontent.com
In Kubernetes, an admission controller such as Kyverno, OPA Gatekeeper or Sigstore policy-controller can enforce rules like these:
Registry hygiene matters as well. Restrict who can push, enable immutable tags, and monitor for account compromise; a Docker Hub flaw that let attackers impersonate users and push images shows why signature verification should not rely on registry trust alone.
A clean image on release day is not a clean image three months later. New CVEs are published against packages that were fine when you built, so the security state of an image changes even if nobody touches it. The fix is a feedback loop rather than a one-time scan.
Measure progress with a small set of metrics: mean time to remediate fixable critical CVEs, percentage of running images built in the last 30 days, and percentage of deployments that passed signature verification.
Those three numbers show whether the pipeline is doing its job far better than a raw CVE total.
Run an open-source scanner such as Trivy (trivy image name:tag) or Grype (grype name:tag) locally or in CI. Configure it to fail the build on fixable high and critical CVEs.
There is no single answer, but minimal images such as distroless or vendor-hardened low-CVE images expose the least. Choose the smallest image that runs your application and rebuild it regularly.
It is a container image that contains only your application and its runtime dependencies, without a shell or package manager. This reduces attack surface and limits what an intruder can do inside the container.
An SBOM records every package and version in an image, so you can quickly find affected workloads when a new vulnerability is disclosed and meet customer or regulatory transparency requirements.
Rebuild at least weekly or whenever the base image publishes a security update, and rescan stored images daily against fresh vulnerability data.
OpenAI has launched GPT-6 Cyber, a security-focused AI model that found 81 new high-severity Firefox…
Shopify is making IP allowlisting mandatory for public apps that call its Admin API, adding…
Microsoft’s Windows Paint vulnerability, CVE-2026-83844, could allow an unauthenticated attacker to execute code over a…
Melbourne, Florida, November 5th, 2026, CyberNewswire OpenMatter Network, a pioneer in decentralized infrastructure for agentic…
A new Android bug named GhostMap can leave a phone stuck in a crash loop…
A China-aligned hacking group is abusing Sogou Input Method, one of the most popular Chinese…