Container security conversations in 2024 still gravitate toward image scanning. Scan your images, patch the CVEs, move on. But organizations that have been running containers in production for several years know the real challenges are elsewhere. Image scanning is necessary but nowhere near sufficient.
Here is what mature container security looks like heading into 2025, informed by the incidents, tooling evolution, and architectural shifts of the past year.
Start With the Base Image
Your container security posture begins with your base image choice. Every layer you add sits on top of this foundation.
Minimal base images reduce attack surface. Distroless images from Google, Chainguard Images, and Alpine-based builds contain a fraction of the packages found in standard Ubuntu or Debian base images. Fewer packages means fewer vulnerabilities and fewer tools available to an attacker who achieves container breakout.
Pin your base images by digest, not tag. Tags are mutable. ubuntu:22.04 today may not be the same image as ubuntu:22.04 next month. Pinning by SHA256 digest ensures reproducibility and prevents supply chain attacks via tag manipulation.
Rebuild regularly. Even minimal base images receive security updates. Automated rebuild pipelines that pull fresh base images and rebuild your containers weekly (or on new CVE disclosures) keep your fleet current without manual intervention.
Verify provenance. Increasingly, base image providers publish provenance attestations and signatures through Sigstore or similar frameworks. Verifying these before building on top of a base image prevents building on a compromised foundation.
Build-Time Security
The build process itself needs hardening:
Multi-stage builds. Separate your build environment from your runtime image. Compilers, build tools, test frameworks, and source code should not exist in the final image. Multi-stage Docker builds make this straightforward.
No secrets in images. This seems obvious, but scanning production images still routinely reveals embedded API keys, database credentials, and private keys. Use build-time secrets (Docker BuildKit secret mounts) and runtime secret injection (Kubernetes Secrets, Vault, cloud provider secret managers) instead.
Reproducible builds. Lock dependency versions, use deterministic build processes, and verify that the same source code produces the same image. This makes it possible to verify that a deployed image corresponds to a specific, audited source state.
SBOM generation at build time. Generate your SBOM during the build process, not by scanning the finished image. Build-time generation captures the full dependency tree with higher accuracy than post-hoc analysis.
Image Scanning: Doing It Right
Image scanning remains important. The key is doing it at the right points and acting on the results:
Scan in CI/CD pipelines. Every image build should trigger a vulnerability scan before the image is pushed to a registry. Block builds that fail policy thresholds.
Scan in registries. Images sitting in registries accumulate new vulnerabilities over time. Continuous scanning of stored images catches CVEs disclosed after the image was built.
Scan at admission. Kubernetes admission controllers can verify that images meet security requirements before allowing them to run. This catches images that bypassed CI/CD scanning or were pulled from unauthorized registries.
Scan at runtime. Runtime scanners detect vulnerabilities in actually running containers, accounting for any differences between the image and the running state.
Prioritize with context. Not every CVE in a container image is exploitable. Prioritize based on:
- Whether the vulnerable package is in the runtime execution path
- Whether the vulnerability is reachable from the container's exposed interfaces
- Whether exploit code exists in the wild
- Whether the container has network access or elevated privileges
Runtime Protection
Build-time and scan-time controls prevent known-bad configurations from deploying. Runtime protection handles everything else:
Network policies. Kubernetes network policies restrict pod-to-pod communication. Default-deny policies combined with explicit allowlists prevent lateral movement if a container is compromised. Most Kubernetes clusters still run with no network policies, meaning every pod can communicate with every other pod.
Seccomp profiles. Restrict the system calls a container can make. Most containerized applications use a small subset of available syscalls. Custom seccomp profiles that allow only required syscalls significantly limit what an attacker can do after container compromise.
AppArmor or SELinux. Mandatory access control profiles restrict file access, network operations, and capability usage at the kernel level. These provide defense-in-depth even if container isolation is partially breached.
Read-only root filesystems. Run containers with read-only root filesystems and use tmpfs or volume mounts for directories that require write access. This prevents attackers from modifying container binaries or writing malicious scripts to disk.
Drop capabilities. Linux capabilities grant specific privileges. Containers should run with the minimum set of capabilities required. Drop all capabilities and add back only what is needed. Never run containers with --privileged in production.
Non-root users. Run container processes as non-root users. This limits the impact of container escape vulnerabilities and restricts file system access within the container.
Supply Chain Verification
Container images are software supply chain artifacts. Treat them accordingly:
Sign images. Use cosign (part of the Sigstore project) or Notary to sign container images. Verify signatures before deployment using admission controllers.
Verify provenance. SLSA provenance attestations document how an image was built, from what source, and by which build system. Verifying provenance ensures images came from trusted build infrastructure.
Allowlist registries. Only allow images from approved registries to run in your clusters. Block pulls from Docker Hub, quay.io, or other public registries unless specifically approved. Maintain internal mirrors of approved external images.
Track image lineage. Maintain records of which base images, build tools, and dependency versions went into each container image. When a vulnerability is found in a base image, you need to know which of your images are affected.
Kubernetes-Specific Hardening
Kubernetes adds its own security considerations beyond individual container hardening:
Pod Security Standards. Use Kubernetes Pod Security Standards (replacing the deprecated PodSecurityPolicy) to enforce security contexts. The "restricted" profile should be the default, with exceptions documented and approved.
RBAC minimization. Role-Based Access Control should follow least privilege. Audit RBAC bindings regularly, as permissions tend to accumulate over time. Service accounts should have only the permissions their workloads require.
Secrets management. Kubernetes Secrets are base64-encoded, not encrypted, by default. Use encrypted etcd, external secret managers (Vault, AWS Secrets Manager, Azure Key Vault), or sealed-secrets to protect sensitive data.
Audit logging. Enable Kubernetes audit logging and monitor for suspicious API calls: privileged container creation, secret access, exec into pods, and RBAC changes.
Control plane hardening. API server access should be restricted, etcd should be encrypted, and control plane components should be regularly updated. Managed Kubernetes services handle some of this, but not all.
Monitoring and Incident Response
Detection and response capabilities are essential:
Runtime anomaly detection. Tools like Falco monitor system calls and container behavior against defined rules, alerting on unexpected processes, network connections, file access patterns, or privilege escalation attempts.
Image drift detection. Detect when running containers diverge from their original images, indicating potential compromise through runtime modification.
Forensic readiness. Container ephemeral nature makes forensics challenging. Ensure logging captures enough detail to investigate incidents, and consider container image archival for post-incident analysis.
How Safeguard.sh Helps
Safeguard.sh integrates into container security workflows at the points that matter most.
At build time, Safeguard.sh generates SBOMs for container images with full dependency resolution, covering both application dependencies and OS packages. These SBOMs feed into continuous vulnerability monitoring that catches new CVEs as they are disclosed, not just at build time.
Policy gates in Safeguard.sh enforce organizational standards before images reach production: vulnerability thresholds, license compliance, and component provenance requirements. This provides the admission control logic that closes the gap between scanning and enforcement.
For organizations building mature container security programs, Safeguard.sh provides the supply chain visibility and policy enforcement layer that connects build-time security to runtime confidence.