Skip to content

Container security

Containers package the application with its dependencies. Their security spans the image (what it contains), the build (how it’s built), and the runtime (how it runs). A misconfigured container is often the escape route to the host or the cluster.

- MINIMAL base image (distroless/alpine) -> less surface, fewer CVEs
- do NOT run as root; unprivileged user (USER in the Dockerfile)
- image vulnerability scanning (Trivy/Grype) before publishing
- no secrets in the image or intermediate layers (dso-secrets); multi-stage build
- pin versions (not :latest) and sign the image (cosign, see dso-cicd)
- multi-stage: compile in one layer, copy only the artifact to the final one (no toolchain)
- minimize layers and packages; clean caches; .dockerignore (don't include .git, secrets)
- scan the Dockerfile config (hadolint, Trivy config)
- image provenance/SBOM (dso-deps) to respond to vulns
- minimal capabilities (drop ALL, add only what's needed); no --privileged
- read-only root filesystem; don't mount the Docker socket in the container (escape)
- seccomp/AppArmor/SELinux active; resource limits (avoid DoS)
- user namespaces; rootless where possible
- --privileged, mounting /var/run/docker.sock or the host FS -> escape to the host
- dangerous capabilities (CAP_SYS_ADMIN), shared kernel -> kernel vulns
- runtime detection (Falco) of anomalous behavior inside the container
Image scan Trivy, Grype, Clair
Dockerfile hadolint, Trivy config
Runtime Falco (detection), gVisor/Kata (hardened isolation)
Registry signing (cosign) + admission policy (dso-k8ssec)
  • Minimal, non-root, scanned, and signed images; no secrets in layers (Secrets management).
  • Runtime with minimal capabilities, read-only FS, and no Docker socket mounted.
  • Falco or other runtime detection for anomalous behavior; hardened isolation if risk demands it.
  • Integrate image scanning in the CI (CI/CD security) and signature-based admission in the cluster (Kubernetes hardening).
  • runC / CVE-2019-5736: container escape by overwriting the runc binary from inside.
  • Leaky Vessels (2024): several escape vulns in container runtimes.
  • Mounting the Docker socket or using —privileged is a recurring escape-to-host cause in real pentests.
  • Minimal base image and non-root (unprivileged USER)
  • Image scanning (Trivy/Grype) in CI before publishing
  • Multi-stage, no secrets in layers, .dockerignore
  • Runtime: drop capabilities, read-only FS, no docker.sock, no —privileged
  • seccomp/AppArmor/SELinux and resource limits
  • Image signing (cosign) and SBOM
  • Runtime detection (Falco) and signature-based admission