Join our Newsletter — 33% off our NHI Course
Home› Guides› Container Security Guide
Guide Cloud Security

Container Security Guide

← All guides
By Lalit Choda, NHI Mgmt Group Updated 17 October 2026 17 min read
On this page

Containers share the host kernel, inherit whatever their image contains and are often started with far more privilege than the application needs, so one weak image or one careless runtime flag can expose the host, its neighbours and the credentials they hold. NIST describes containers as "a form of operating system virtualization", which is exactly why isolation depends on configuration rather than on a hypervisor boundary. This guide covers the full container lifecycle: base images and Dockerfile hardening, scanning, SBOMs and signing, registries, the Docker daemon and host, runtime isolation (capabilities, seccomp, AppArmor and SELinux, read-only filesystems, rootless mode), container escape routes and runtime detection. It is written for platform engineers, DevSecOps teams and security architects running Open Container Initiative (OCI) images on Docker, containerd or CRI-O, whether or not Kubernetes is on top. Orchestrator hardening is out of scope here; Kubernetes service account tokens are covered in the Kubernetes NHI Security Guide linked below.

Key takeaways

  • Most container risk is decided at build time. A minimal or distroless base, a non-root USER, pinned versions and no secrets in layers remove whole classes of findings before a scanner ever runs.
  • Trust images by digest and signature, not by tag. NIST SP 800-190 notes that the latest tag is "only a label attached to the image and not a guarantee of freshness"; verify signatures and pin digests at deploy time.
  • The Docker socket is root on the host. Never mount /var/run/docker.sock into a container or expose the daemon on TCP without TLS; OWASP warns that mounting the socket read-only does not make the API read-only.
  • Layer the runtime controls. Drop all capabilities, set no-new-privileges, keep the default seccomp profile, use AppArmor or SELinux, run read-only and never use --privileged; each blocks a different escape route.
  • Detect at runtime, because prevention will miss things. Syscall-level tools such as Falco flag shells in containers, writes to /etc and namespace changes that image scanning cannot see.

Where container risk sits

NIST SP 800-190 groups container risk into five areas; using them stops a programme over-investing in image scanning while the daemon, registry or host stay weak.

SP 800-190 areaTypical risks (section)Primary controls
Images (3.1)Vulnerable components, configuration defects such as running as root or an SSH daemon, embedded malware, embedded clear text secrets, untrusted imagesMinimal bases, scanning with quality gates, secret scanning, signing, trusted image set
Registries (3.2)Insecure connections, stale images, weak authentication and authorisationTLS only, authenticated pulls, tag immutability, pruning, scoped push rights
Orchestrator (3.3)Unbounded admin access, unauthorised access, flat networks, mixed sensitivity levels, node trustRBAC, network policy, separating workloads by sensitivity onto different hosts
Containers (3.4)Runtime software vulnerabilities, unbounded network access, insecure runtime configuration, app vulnerabilities, rogue containersPatched runtimes, egress control, capabilities, seccomp, LSM profiles, runtime detection
Host OS (3.5)Large attack surface, shared kernel, component vulnerabilities, improper user access, filesystem tamperingContainer-specific host OS, kernel patching, restricted host access, integrity monitoring

Two SP 800-190 principles shape everything else: containers should be "operated as stateless entities that are deployed but not changed", so fixes go into a rebuilt image rather than a patched running container, and "a given host kernel only runs containers of a single sensitivity level", because the shared kernel is the weakest boundary.

Building secure images

Base image choice

  • Distroless and minimal bases: Google's distroless images contain "only your application and its runtime dependencies" and no package manager or shell. The static image is about 2 MiB, against about 5 MiB for Alpine and 124 MiB for Debian, and the project notes that this "improves the signal to noise of scanners". Use the :nonroot variants, and keep :debug (which adds a BusyBox shell) out of production.
  • Language and OS bases: where a full distribution is needed, use a slim official variant, pin the version, rebuild often and switch to the non-root user the image provides (official Node.js images, for example, include a node user).
  • Golden images: SP 800-190 says organisations "should maintain a set of trusted images and registries" and allow only images from that set to run. A small catalogue of approved, regularly rebuilt bases is far easier to patch.

Dockerfile hardening

  • Run as non-root: create a user and set USER; SP 800-190 also says SSH and remote shell tools should not be enabled inside containers.
  • Multi-stage builds: compile in a builder stage and copy only the artefact into the final stage, so compilers, package caches and test tooling never ship.
  • Prefer COPY to ADD, pin versions and avoid curl-pipe-to-shell: OWASP lists all three as Dockerfile checks to automate in CI.
  • Never put secrets in layers: Docker's documentation states that "Build arguments and environment variables are inappropriate for passing secrets to your build" because they persist in the image. Deleting a file in a later layer does not remove it from the earlier one. Use BuildKit secret mounts, which appear at /run/secrets/<id> only for the duration of one RUN step.

An illustrative fragment combining these points:

FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN --mount=type=secret,id=netrc,target=/root/.netrc \
    CGO_ENABLED=0 go build -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian13:nonroot
COPY --from=build /out/app /app
USER nonroot
ENTRYPOINT ["/app"]

Build it with docker build --secret id=netrc,src=$HOME/.netrc . so the credential never enters a layer. See the Secrets Management Guide.

Scanning, SBOMs, signing and provenance

  • Scan in the pipeline and in the registry: SP 800-190 recommends container-aware vulnerability tools with policy-driven "quality gates" in build and deployment. Open source scanners include Trivy, Grype and Clair; OWASP also lists Docker Bench for Security for host and daemon checks, and Gitleaks, TruffleHog and ggshield for secrets in images. Rescan stored images daily.
  • Generate an SBOM and provenance at build: BuildKit attaches attestations in in-toto format to the image index. --sbom=true adds an SPDX SBOM; minimal (mode=min) provenance is added by default and --provenance=mode=max records more build detail. An SBOM answers "which images contain this library?" when the next critical CVE lands.
  • Sign images and verify before deploy: Sigstore cosign supports keyless signing tied to a CI identity and key-based signing. Verification checks the signature and that the signed digest matches the image, for example cosign verify <image> --certificate-identity=... --certificate-oidc-issuer=..., and cosign verify-attestation checks SBOM or provenance attestations. Distroless images are themselves keyless-signed, so verify bases before building on them.
  • Deploy by digest: SP 800-190 says operations should use "immutable names that specify discrete versions". Pin image@sha256:... in deployment manifests and let automation bump digests.

See the SLSA and Build Provenance Guide for provenance levels and the Open Source Security Guide for dependency risk inside images.

Registry security

  • Authenticate every pull of proprietary images: SP 800-190: "All access to registries that contain proprietary or sensitive images should require authentication." Use TLS only and remove anonymous pull from internal repositories.
  • Separate push from pull: only the build pipeline's identity should push to release repositories; developers and clusters get pull-only rights. A push credential is a supply chain key: ATT&CK T1525 Implant Internal Image describes adversaries planting a backdoored image in an organisation's own registry.
  • Make tags immutable: in Amazon ECR, --image-tag-mutability IMMUTABLE makes a push of an existing tag fail with ImageTagAlreadyExistsException; IMMUTABLE_WITH_EXCLUSION allows exceptions such as latest. Other registries offer equivalent settings.
  • Prune stale images: SP 800-190 treats stale images as a risk in their own right; apply lifecycle rules so unpatched old versions cannot be pulled by mistake.
  • Control public sources: pull third-party images through a scanning proxy or mirror, not directly from public hubs.

Daemon, runtime and host hardening

Docker's documentation is blunt: "only trusted users should be allowed to control your Docker daemon", because a user who can start containers can mount the host's / and "alter your host filesystem without any restriction". Membership of the docker group is therefore equivalent to root on the host.

  • Keep the API local: the daemon listens on a Unix socket by default. If remote access is needed, use TLS on port 2376 or DOCKER_HOST=ssh://; never the plain text port 2375. Exposed Docker APIs are a standard worm entry point, as the TeamTNT Worm 2020 showed.
  • Use a container-specific host OS where possible: SP 800-190 recommends them to cut attack surface, with read-only system partitions.
  • Patch the runtime stack: runc, containerd, CRI-O and the kernel are all in scope. CVE-2024-21626 in runc 1.1.11 and earlier let a process started with runc exec get a working directory in the host filesystem; runc 1.1.12 fixed it.
  • Benchmark the host: the CIS Docker Benchmark (version 1.9.0 at the time of writing) is consensus-based guidance covering host, daemon, image and runtime configuration; Docker Bench for Security automates many of its checks.
OptionWhat runs as rootProtects againstTrade-offs
Default (rootful daemon)Daemon and, unless USER is set, the container processLittle beyond namespaces, default capabilities and seccompWidest compatibility; worst blast radius
--userns-remapDaemon only; container root maps to an unprivileged host UIDEscaped container root lands as an unprivileged userOWASP notes the daemon still runs as root; some volume ownership issues
Rootless modeNothing: daemon and containers run inside a user namespaceDaemon and runtime vulnerabilitiesNeeds newuidmap, newgidmap and at least 65,536 subordinate IDs; OWASP notes it does not protect against kernel vulnerabilities
Sandboxed runtime (gVisor, Kata Containers)Varies; adds a user-space kernel or lightweight VM boundaryShared-kernel exploits for untrusted or multi-tenant codePerformance and compatibility costs; use for the highest-risk tiers

Runtime isolation controls

These controls overlap deliberately; treat any exception as a reviewed risk.

ControlDockerKubernetes securityContextWhat it blocks
Non-root user-u 4000 or USERrunAsNonRoot: true, runAsUserRoot-owned host files after an escape; many local escalations
Capabilities--cap-drop all --cap-add CHOWNcapabilities: drop: ["ALL"]Raw sockets, mounts, module loading, other root powers
No privilege escalation--security-opt=no-new-privilegesallowPrivilegeEscalation: falsesetuid binaries gaining privileges
SeccompDefault profile; custom via --security-opt seccomp=profile.jsonseccompProfile: type: RuntimeDefaultDangerous syscalls such as keyctl, bpf, kexec_load
AppArmor or SELinuxdocker-default AppArmor profile or SELinux labelsappArmorProfile, seLinuxOptionsFile and capability access outside the profile
Read-only root--read-only --tmpfs /tmpreadOnlyRootFilesystem: trueDropping tools and persistence in the container
Resource limits--memory, --pids-limit, --ulimitrequests and limitsFork bombs, noisy neighbours, some cryptomining impact
Never privilegedno --privilegedprivileged: falseFull device and capability access to the host

Docker's default seccomp profile is an allowlist that "disables around 44 system calls out of 300+" and is "moderately protective while providing wide application compatibility". Docker advises against changing it, and OWASP advises against disabling it; running with seccomp=unconfined removes a key escape barrier. For networking, SP 800-190 says organisations "should control the egress network traffic sent by containers". Use user-defined networks rather than the default bridge, and note OWASP's warning that Docker manages its own iptables rules and can bypass host firewalls such as UFW, so bind published ports to 127.0.0.1 when they should be local.

Container escape: routes and blocks

ATT&CK T1611 Escape to Host lists the main routes. Each maps to a control above, so enforce them by policy rather than leaving them to teams.

  • Privileged containers: used to run commands or load a kernel module on the host. Block --privileged and privileged: true outright.
  • Host filesystem mounts: a bind or hostPath mount of / or sensitive paths gives direct host access. Disallow hostPath in shared clusters and review every bind mount.
  • Mounted management sockets: a compromised container with docker.sock can start a new privileged container. ATT&CK also tracks reading credentials from container APIs as T1552.007.
  • Syscall abuse: T1611 cites unshare and keyctl; seccomp and dropped capabilities remove most of this.
  • Kernel and runtime vulnerabilities: patching, minimal hosts, sensitivity-based placement and sandboxed runtimes.

Runtime detection

Falco, a graduated CNCF project originally created by Sysdig, parses Linux syscalls at runtime through a modern eBPF probe (the default) or a kernel module, and evaluates them against YAML rules. Plugins add sources such as Kubernetes audit events. Documented detections include privileged container activity, namespace changes via setns, writes to /etc, /usr/bin and /usr/sbin, shell and SSH binaries being executed, and unexpected network connections. OWASP also names Tetragon and Cilium's eBPF tooling for runtime monitoring.

ATT&CK technique (v20)What it looks like in containersSignal to collect
T1610 Deploy ContainerNew container started from an unknown image, often privilegedDaemon or orchestrator events; image not in the approved registry
T1609 Container Administration Commanddocker exec or kubectl exec into a running workloadDaemon and audit logs; interactive shell spawned in container
T1611 Escape to HostMount, unshare, namespace changes, host path accessFalco namespace and mount rules; seccomp denials
T1612 Build Image on HostImage built directly on a host to avoid registry controlsBuild API calls on runtime hosts that should never build
T1525 Implant Internal ImageBackdoored image pushed to an internal registryRegistry push logs; unsigned digests; push by non-pipeline identity
T1613 Container and Resource DiscoveryEnumerating containers, images and API endpointsUnusual API list calls from workloads
T1496 Resource HijackingCryptominers in compromised containersCPU anomalies; connections to mining pools

Send daemon logs and runtime alerts to the SIEM with image digest, container ID and host attached, and keep the daemon at the default info log level as OWASP recommends. See the Detection Engineering Guide.

Where identity fits

Registry credentials, CI push tokens, cloud keys and API keys are what attackers in a compromised container hunt for. Supply secrets at runtime from a secrets manager or orchestrator mount, as SP 800-190 says ("Secrets should be stored outside of images and provided dynamically at runtime as needed"), prefer short-lived workload identity over static keys, and give the push identity to the pipeline only. See the Cloud Workload Identity Guide and, for service account tokens, the Kubernetes NHI Security Guide.

Implementation roadmap

  1. Inventory: list container hosts, registries, base images and who can reach each daemon. Fix any daemon on TCP 2375 and any container with docker.sock mounted or --privileged set first.
  2. Standardise bases: publish a small set of approved, signed, regularly rebuilt base images (distroless or slim, non-root) and migrate the highest-exposure services first.
  3. Add pipeline gates in report-only mode: scanning, Dockerfile linting and secret scanning that report without failing builds for two to four weeks, so teams can fix backlogs and you can tune thresholds.
  4. Enforce gates: fail builds on critical, fixable vulnerabilities and on any secret found; allow time-limited, recorded exceptions.
  5. Sign, attest and lock the registry: sign in CI, generate SBOMs, turn on tag immutability, restrict push to pipeline identities, then require signature verification at deploy time, starting with one environment.
  6. Harden runtime defaults: roll out non-root, dropped capabilities, no-new-privileges and read-only roots through shared templates; pilot on stateless services before stateful ones.
  7. Deploy runtime detection: start Falco or an equivalent with default rules in alert-only mode, tune noisy rules for a few weeks, then route high-confidence alerts to response playbooks.
  8. Roll back safely: because images are immutable and deployed by digest, rollback means redeploying the previous signed digest; keep the last known good digests and keep emergency exceptions time-limited and logged.

Decision guidance

  • Distroless vs slim distribution bases: choose distroless for compiled and well-packaged runtimes where nobody needs a shell; choose slim distributions where native dependencies need a package manager at build time, and use multi-stage builds to keep it out of the final image.
  • Rootless vs userns-remap: rootless removes root from the daemon too and suits developer machines and single-tenant build hosts; userns-remap is a smaller change for existing rootful fleets. Neither replaces kernel patching.
  • Sandboxed runtimes: use them for untrusted code, customer-supplied workloads and multi-tenant platforms, not by default for first-party services.
  • Small organisations: rely on managed registries with built-in scanning and immutability, official or distroless bases and a handful of enforced runtime defaults. Large organisations: run a golden image programme, central signing, admission policy and fleet-wide runtime detection, often within a CNAPP. See the CNAPP Guide.

Detection and measurement

  • Image hygiene: percentage of running containers built from an approved base image, and median age of those bases.
  • Vulnerability exposure: count of running images with critical, fixable vulnerabilities, and mean time from fix availability to redeploy.
  • Privilege posture: number of running containers that are privileged, run as root, mount docker.sock or a sensitive host path; the target for the first three is zero outside reviewed exceptions.
  • Supply chain integrity: percentage of deployments by digest with a verified signature.
  • Secrets: secrets found in images per month, and time to revoke each one.
  • Runtime alert quality: high-severity runtime alerts per week and the share that were true positives after triage.

Common failure patterns

  • Secrets baked into public images: credentials left in layers or build artefacts are recoverable by anyone who pulls the image. The Docker Hub Secrets Leak 2025 found cloud, CI and AI keys in 10,456 public images, and the PyPI Admin GitHub Token Leak 2024 came from a token in a compiled Python file inside a public image.
  • Exposed Docker daemons: an unauthenticated API is an open door for container deployment and credential theft, as in the Carbonato Botnet 2026 on exposed Docker hosts.
  • Trusting a tag: mutable tags let a poisoned image replace a trusted one silently. The Checkmarx KICS Supply Chain Attack 2026 poisoned Docker images published under a trusted project's name; digest pinning and signature verification limit that exposure.
  • "Temporary" privileged containers: a debug container started with --privileged or the Docker socket stays for years and becomes the escape path.
  • Scanning without redeploying: long-running containers keep the old image; measure what is running, not what was built.
  • Disabling seccomp or AppArmor to fix one error: unconfined becomes the template default. Write a narrow custom profile instead.

Framework mapping

Control areaNIST SP 800-53 Rev. 5NIST CSF 2.0CIS Controls v8.1ISO/IEC 27001:2022 Annex A
Hardened images and runtime configurationCM-6, CM-7PR.PS-014.1A.8.9
Image and runtime vulnerability scanningRA-5, SI-2ID.RA-01, PR.PS-027.5, 7.6A.8.8
Least privilege for daemon and containersAC-6PR.AA-055.4A.8.2
Signing and integrity verificationSI-7PR.PS-0616.1A.8.19, A.8.25
Runtime monitoringSI-4, AU-12DE.CM-098.2, 13.1A.8.15, A.8.16

Practitioner checklist

  • No Docker daemon listens on TCP 2375; remote access uses TLS on 2376 or SSH, and docker group membership is treated as root.
  • No container mounts docker.sock or runs --privileged outside a reviewed, time-limited exception.
  • All production images come from an approved, signed base set, run as non-root and are deployed by digest.
  • Builds use secret mounts; secret scanning fails any build that leaves a credential in a layer.
  • Vulnerability scanning runs in CI and daily against registries, with gates on critical, fixable findings.
  • SBOM and provenance attestations are generated for every release image and signatures are verified before deploy.
  • Registries require authentication, push is limited to pipeline identities and tags are immutable.
  • Runtime defaults drop all capabilities, set no-new-privileges, keep seccomp at RuntimeDefault and use read-only roots.
  • runc, containerd or CRI-O and host kernels are on a defined patch cycle; hosts are checked against the CIS Docker Benchmark.
  • Runtime detection is deployed on every container host with alerts in the SIEM.

Standards and references

Related NHI Mgmt Group resources: Kubernetes NHI Security Guide · SLSA and Build Provenance Guide · Secrets Management Guide · Linux Server Hardening Guide · CI/CD Pipeline Identity Security Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Written and reviewed by Lalit Choda, NHI Mgmt Group. Last updated 17 October 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org