Container Image Security
itSoftware supply chain security
Container Image Security
A container image is a packaged filesystem plus configuration. It carries the application, runtime libraries, and startup settings that a container runtime needs. That convenience also creates a concentrated security boundary: every included file, package, credential, and default can travel from a developer's build into production.
Container image security is the practice of controlling that package across its full lifecycle. You choose trusted inputs, build with fewer unnecessary components, record what happened, test the result, distribute it through a protected registry, and verify it before deployment. You keep reassessing published images because vulnerability knowledge changes after a build finishes.
The useful mental model is a sealed shipment with an inventory and chain of custody. The image is the shipment. Its digest identifies the exact contents. An SBOM lists components. Provenance describes how the shipment was produced. A signature links an identity to the artifact. Policy decides whether the evidence is sufficient for a destination.
None of those controls answers every question. A digest proves which content you selected, not that the content is safe. A signature proves a verification relationship, not that the signer made a secure image. An SBOM supplies inventory, not a risk verdict. A vulnerability scan compares observable components with current advisory data, so a clean result can change when new advisories appear.
What an image contains
The Open Container Initiative image format defines an image manifest with a configuration object and an ordered set of filesystem layers. Each object is referenced by a digest. A registry stores and distributes these objects. A tag gives people a convenient name, while a digest identifies content through a cryptographic hash.
This distinction changes deployment safety. A tag such as app:2.4 can be moved to different content. A digest reference such as app@sha256:... selects one exact manifest. Pinning by digest makes a deployment repeatable and prevents a later tag change from silently selecting another image.
Layers also affect secret handling. Deleting a secret in a later build step does not reliably remove it from an earlier layer. Docker therefore warns against passing secrets through build arguments or environment variables. Build secret mounts make a secret available to a build step without placing it in the resulting image layer.
The main risks
NIST groups image risks into five practical categories: vulnerable software, configuration defects, embedded malware, embedded clear-text secrets, and untrusted images. Those risks come from both your application and everything underneath it.
A base image is an upstream dependency. Its packages, default user, certificates, shell, and utilities become part of your result. A large base is not automatically insecure, but every unnecessary component adds material to inventory, patch, and review. Multi-stage builds help by separating build tools from the final runtime image. A final stage can contain only the application and the runtime components it needs.
Configuration matters even when every package is current. An image without a non-root user may start with more privilege than the application needs. Extra network services or debugging tools can add unwanted behavior. Image hardening reduces these defaults, while runtime controls still limit what a container may do after it starts.
Registry security is part of image security. Weak access control can allow unauthorized pushes or expose private images. Stale images can remain deployable long after fixes exist. Protect push permissions, retain audit evidence, use encrypted registry connections, and apply retention rules that preserve needed rollback versions without keeping every obsolete artifact available forever.
A secure image lifecycle
1. Control inputs
Start with approved registries and maintained base images. Pin important inputs by digest so the build records the exact content it used. Review the update process at the same time. A permanent pin without an update mechanism gives repeatability but can leave a known-vulnerable base in place.
Treat every FROM, downloaded archive, package repository, and build tool as a supply-chain input. Record resolved dependencies in build provenance where your build platform supports it. This evidence helps a consumer check whether the build used expected source, configuration, dependencies, and builder identity.
2. Build narrowly
Keep the build definition in version control. Use multi-stage builds to leave compilers, package managers, and temporary files out of the final stage when the application does not need them. Set a non-root runtime user when the workload supports it. Use build secret mounts instead of build arguments or environment variables for sensitive values.
Smaller is a means, not the security objective. The objective is an explainable image with the minimum required behavior. A tiny image from an unknown publisher can be a worse choice than a larger image with a maintained source, published update policy, and verifiable provenance.
3. Produce evidence
Generate an SBOM during the build or from the final artifact. An SBOM records software components and their supply-chain relationships. Generate provenance from the trusted build platform so it describes the actual build rather than a developer's recollection.
Sign the image or its attestation after the final digest exists. In keyless Sigstore verification, the verifier checks the expected certificate identity and OpenID Connect issuer. Cosign also checks that the digest in its signature payload matches the image by default.
4. Analyze and decide
Scan the final image, not only the source tree. Image analysis can inventory operating-system and language packages, then compare them with security advisories. Findings need context: affected package, installed version, fixed version, reachability, exposure, available compensating controls, and workload importance.
Do not reduce policy to one severity number. Advisory sources can assign different severities, and scanners can miss software they cannot identify. Define explicit release criteria. For example, require an approved base, a digest reference, an SBOM, valid provenance, an accepted signer identity, and no unapproved findings that exceed your risk threshold.
5. Verify at deployment
Verification has more value when it gates the destination. A continuous integration check can stop a bad release, but admission policy can also stop an unsigned or unexpected image from entering a cluster through another path.
Deploy by digest. Kubernetes documents that a digest pins the code selected for a workload even if a registry tag later changes. Keep the human-readable tag in release metadata for navigation, but make the digest the deployed identity.
6. Reassess and rebuild
An image does not become permanently safe when it passes a build-time scan. NIST notes that new vulnerabilities can be discovered after an image is created. Keep the SBOM or another reliable inventory, reevaluate deployed digests against new advisory data, and rebuild from patched inputs.
Prefer replacement over manual repair inside a running container. Fix the source or build definition, create a new image, verify its evidence, and redeploy it. This preserves a traceable relationship between source, build, artifact, and runtime.
Where image security stops
Image controls do not replace runtime security. A well-built image can still run with excessive Linux capabilities, writable host mounts, exposed credentials, or unrestricted network access. A vulnerable kernel is outside the image but inside the container's isolation boundary. Protect the host, runtime, orchestrator, identities, secrets, and network alongside the image pipeline.
Image scanning also does not replace application security testing. A scanner may identify known vulnerable components, but it does not prove that authorization logic, input validation, or business rules are correct. Use source analysis, dependency review, testing, and runtime monitoring for those concerns.
The goal is defensible selection. For every deployed digest, you should be able to answer four questions:
- What components and configuration are inside?
- Which source, dependencies, and builder produced it?
- Did an expected identity authorize this exact artifact?
- Does current policy permit it in this environment?
If the evidence cannot answer one question, treat that as a visible gap rather than an assumption.
