
The most popular Docker security advice is also the least complete: scan the image, fix the CVEs, and call the container secure. That approach can identify vulnerable packages, but it won't tell you whether the Docker daemon is exposed, whether a container can access the host, whether build secrets were preserved in an image layer, or whether an attacker can abuse the orchestration control plane.
A pentester starts somewhere else. The assessment follows trust boundaries from the image registry to the host kernel, from the daemon API to runtime behavior, and from developer workstations to production admission controls. The objective isn't a green scanner result. It's evidence that an attacker can't turn a weak image, an exposed management socket, or an excessive capability into control of the underlying environment.
Table of Contents
- Why Docker Container Security Starts With the Threat Model
- Kernel Isolation Primitives You Need to Understand
- Hardening the Image Supply Chain End to End
- The Exposed Management Plane Most Guides Miss
- Runtime Defenses and CI/CD Gateways
- Mapping Docker Controls to CIS, NIST, and Compliance
- A Pentester Verification Checklist With Example Commands
Why Docker Container Security Starts With the Threat Model
Running Trivy against an image is useful, but it isn't a Docker container security program. A 2017 large-scale study of 356,218 Docker Hub images found more than 180 vulnerabilities on average across all versions of official and community images. Even the latest official images averaged more than 70 vulnerabilities, and more than 80% of both image categories had at least one high-severity vulnerability, according to the Docker Hub image security study. Scanning would have exposed part of that problem, but it wouldn't have addressed daemon exposure or runtime privilege.
The first pass in a penetration test is a layered threat model:
- Image supply chain: A supply-chain attacker compromises a base image, build dependency, registry account, or signing workflow. An insider with registry credentials can also push a trusted-looking tag.
- Container configuration: A developer or operator leaves
--privileged, broad capabilities, writable host mounts, or sensitive environment variables in the deployment. A stolen CI credential can make those settings operationally dangerous. - Runtime and host: A script kiddie finds an exposed Docker API through internet-wide scanning, while an advanced attacker pivots from a developer laptop into a daemon, then abuses kernel-facing permissions to reach the host.
- Orchestrator control plane: Kubernetes or Swarm permissions can turn a compromised workload into a deployment, secret, or node-level problem if authorization is too broad.

What the attacker actually tests
An attacker doesn't need every layer to fail. A poisoned base image may provide code execution inside the workload, while an exposed daemon API may provide a direct path to create a privileged container. A stolen registry credential can be more valuable than a kernel exploit because defenders may trust the resulting image.
The patch problem is structural, not just procedural. The same 2017 study found that about 50% of official and community images hadn't been updated for hundreds of days, showing why a secure build must measure freshness instead of assuming that an official tag is current. A later scholarly review reports that the MITRE database lists 571 DockerHub container-engine vulnerabilities, while the current CIS Docker Benchmark version 1.8.0 defines 118 controls across host configuration, daemon hardening, images, runtime settings, security operations, and Swarm. Those figures are documented in the Docker attack and defense review.
Pentest rule: Treat image scanning as one signal. The finding is only closed when the image, daemon, host, runtime, and control plane agree on the same security boundary.
Kernel Isolation Primitives You Need to Understand
A container is a process using Linux isolation features. Docker doesn't create a miniature virtual machine, and a pentester needs to know which kernel boundary each setting enforces.
The five controls that form the boundary
Namespaces provide separate views of processes, networking, mounts, IPC, UTS identity, and users. User namespaces matter because they can map container UID 0 to an unprivileged host UID. To inspect the distinction during an authorized test, compare the process and mount views from a disposable container:
docker run --rm alpine sh -c 'readlink /proc/1/ns/pid; readlink /proc/1/ns/mnt; cat /proc/self/uid_map'
For a host-side experiment, unshare can create isolated views:
unshare --pid --fork --mount-proc sh
That command demonstrates process isolation, but it isn't a proof that every Docker setting is safe.
Cgroups, especially cgroups v2, constrain CPU, memory, and process consumption. Without resource limits, a compromised process can consume host resources even if it can't escape. Inspect the effective configuration with docker inspect, then confirm live behavior through docker stats.
Capabilities split root's kernel powers into smaller privileges. Docker drops many capabilities by default, but the safe approach is explicit reduction:
docker run --rm --cap-drop=ALL --cap-add=NET_BIND_SERVICE alpine true
Seccomp filters system calls with Berkeley Packet Filter rules. Docker's default profile allows roughly 300 syscalls, and the Docker security model reference recommends combining seccomp with MAC controls, read-only filesystems, and capability removal. A custom profile is applied with:
docker run --rm --security-opt seccomp=profile.json alpine true
AppArmor or SELinux supplies mandatory access control. These policies constrain file and process actions even when a process gains more discretionary authority inside the container.
| Primitive | What It Isolates | Docker Flag | Common Misconfiguration |
|---|---|---|---|
| Namespaces | Process, network, mount, IPC, UTS, and user views | --pid, --network, --userns |
Sharing the host namespace |
| Cgroups v2 | CPU, memory, and process consumption | --cpus, --memory, --pids-limit |
No resource limits |
| Capabilities | Individual kernel privileges | --cap-drop, --cap-add |
Using --privileged or broad additions |
| Seccomp | Allowed system calls | --security-opt seccomp= |
Disabling the default profile |
| AppArmor or SELinux | Mandatory file and process access | --security-opt apparmor= |
Running unconfined |
Docker's defaults vary by engine, host distribution, rootless mode, and orchestration layer. Rootless Docker changes the daemon's privilege model, while Podman uses a different architecture and can apply rootless operation as a normal workflow. Don't infer effective isolation from the command line alone. Read /proc/self/status, inspect CapEff, review SecurityOpt, and trace behavior with an approved syscall monitor such as strace, Falco, or Tetragon.
Hardening the Image Supply Chain End to End
Image security starts before docker build. Choose a maintained, minimal base such as a distroless, Chainguard, or slim Debian image when the application supports it. Avoid floating latest tags, select a known digest, and document why that base is trusted. A smaller image can reduce available tooling, but that trade-off is valuable only if operators have an alternate debugging path and the build remains reproducible.
Multi-stage builds keep compilers, package managers, and test artifacts out of the runtime image. They also create a natural review boundary:
FROM golang:stable AS buildWORKDIR /srcCOPY . .RUN go build -o /out/app ./cmd/appFROM gcr.io/distroless/staticCOPY --from=build /out/app /appENTRYPOINT ["/app"]
Use immutable references and verify what enters the artifact:
docker scout cves myregistry.example/app@sha256:...syft packages myregistry.example/app:release -o spdx-json > sbom.jsoncosign sign --key cosign.key myregistry.example/app@sha256:...
A scanner reports known package weaknesses. Syft helps produce a software bill of materials. Cosign provides an authenticity control. None of these, alone, proves that the build process was trustworthy. For a broader software composition analysis workflow, use the software composition analysis resource.

Promotion needs an enforceable policy
A CI job that prints vulnerabilities but still publishes the image is advisory, not preventive. Gate promotion on severity, provenance, signature, base-image policy, and secret detection. An OPA or Conftest rule can reject floating tags:
package docker.security
deny[msg] { input.image.tag == "latest" msg := "floating image tags are not permitted"}
The exact policy should match risk and operational reality. Blocking every vulnerability can stop delivery when upstream remediation isn't available, while allowing everything creates silent debt. Record exceptions with an owner, expiration, and compensating control.
Build-time secrets need separate treatment. Don't place credentials in ARG, ENV, copied configuration files, or temporary paths that persist in an earlier layer. Use BuildKit secret mounts, keep credentials outside the build context, and test the final image and its history for remnants. A 2025 investigation reported 10,456 Docker Hub images leaking production credentials across 205 namespaces, with 42% of exposed images containing five or more secrets, as documented in the Docker credential exposure analysis. That is why trusted provenance and secret hygiene belong beside CVE scanning.
The Exposed Management Plane Most Guides Miss
The Docker daemon is often the highest-priority target in an assessment. A mounted /var/run/docker.sock, an unauthenticated TCP listener on port 2375, or a poorly protected TLS endpoint on port 2376 can let an attacker ask the daemon to create containers, mount host paths, or alter workloads. Image hardening won't compensate for an administrative API that accepts hostile requests.
Independent reporting found an average of 485 published Docker API default ports worldwide each month in 2025, with exposure concentrated in China, Germany, the U.S., Brazil, and Singapore. The Kaspersky analysis of Docker exposure also notes malware targeting exposed Docker APIs, while Akamai has documented active targeting in the wild.
What I verify during an engagement
I check cloud security groups, host listeners, container mounts, and internal routing rather than relying on a web reverse proxy review. Authorized reconnaissance can include Shodan-style searches for Docker service fingerprints, Nmap NSE scripts selected for the environment, and tightly scoped probes:
curl --fail curl --fail
A response from /version or /info is evidence that the management plane is reachable. It isn't permission to continue exploiting it. Preserve the response, source location, authentication state, and segmentation context, then stop or proceed under the engagement rules.
| Exposure Vector | Attacker Capability | Detection Signal | Recommended Control |
|---|---|---|---|
| Docker socket mounted into a container | Daemon-level workload creation | /var/run/docker.sock in mounts |
Remove the mount, or use a tightly scoped socket proxy |
| TCP daemon without mutual TLS | Remote daemon administration | Listener on the Docker API port | Keep the daemon off routable interfaces |
| Weak TLS trust model | Unauthorized client access | Broad or unmanaged client certificates | Use --tlsverify with a minimal CA |
| Shared host daemon | Cross-project workload influence | Unexpected users or containers | Prefer rootless, isolated daemons |
| Swarm or orchestrator endpoint | Deployment and secret manipulation | Excessive control-plane permissions | Segment and enforce least privilege |
A read-only socket mount isn't automatically safe. The socket is an authority channel, and many clients can perform privileged actions even when the filesystem mount uses read-only mode. Rootless operation and a narrowly scoped socket proxy are stronger choices for shared environments. Document each result against NIST SP 800-190 section 4.3.1 and the CIS host configuration chapter, then retain the attack surface mapping resource as part of the assessment methodology.
Runtime Defenses and CI/CD Gateways
A defensible pipeline connects build evidence to admission decisions and live response. The build emits an SBOM with Syft, signs the immutable image with Cosign, and stores provenance where the deployment system can verify it. Admission then rejects artifacts that don't meet policy, rather than allowing an untrusted image to become a runtime investigation.
Make deployment policy executable
OPA Gatekeeper or Kyverno can block :latest, privileged escalation, hostPath mounts, missing resource limits, and images without an approved signature. A policy should evaluate the rendered deployment, not only the source Dockerfile, because Helm values and environment overlays can reintroduce risky settings.
Runtime configuration should reinforce the kernel controls already discussed:
- Filesystem: Use a read-only root filesystem and a
tmpfsmount for temporary writes. - Privileges: Drop all capabilities, then add only the narrow capability the application requires.
- Process behavior: Set
no-new-privilegesand apply a custom seccomp profile. - Network behavior: Restrict egress and alert on unexpected connections to known command-and-control ranges.
- Detection: Use Falco or Tetragon rules for shell execution, capability changes, unusual mounts, and suspicious process ancestry.
A control is more useful when it produces a usable signal. Falco can alert on an unexpected exec inside a container, while Tetragon can associate kernel events with workload identity. Send those events to the SIEM with container ID, image digest, namespace, node, user, and timestamp. Avoid relying on an alert that says only “container activity detected.”

Response must be tested, not assumed
Define what happens after a high-confidence event. A pod-level kill action can limit exposure, while Slack or Jira webhooks notify the responsible team. Immutable event records in the SIEM support investigation and provide evidence for SOC 2 CC7 monitoring activities, but an automated kill can also destroy volatile evidence. Use severity-based response, preserve logs and metadata first, and rehearse the workflow with a disposable workload.
Mapping Docker Controls to CIS, NIST, and Compliance
Compliance evidence becomes more useful when one technical test supports several frameworks. The CIS Docker Benchmark provides a practical secure-configuration baseline for the host, daemon, images, and runtime. Docker's own benchmark tooling is based on CIS Docker Benchmark v1.6.0, while the current benchmark version is 1.8.0, so record the exact version used rather than describing the result as “CIS compliant.” The CIS Docker Benchmark is the appropriate source for the benchmark's scope.
NIST SP 800-190 adds stack coverage that a host checklist alone misses. Its layered model addresses the image, registry, orchestrator, container, host operating system, and hardware, which makes it useful for penetration-test scoping and evidence classification. The NIST container security guide gives the assessment team a way to place a finding at the correct layer.
| Control Area | CIS Docker Benchmark | NIST SP 800-190 | SOC 2 / PCI-DSS | Evidence Artifact |
|---|---|---|---|---|
| Daemon configuration | Host and daemon hardening | Host and container layers | CC6, PCI-DSS 1 | docker info, daemon configuration, benchmark output |
| Image provenance | Image controls | Image and registry layers | CC6, PCI-DSS 6 | Signature verification, SBOM, build record |
| Runtime privilege | Container runtime controls | Container and host layers | CC6, CC7, PCI-DSS 1 | docker inspect, policy output, runtime alerts |
| Network exposure | Host and daemon controls | Registry, orchestrator, and host layers | CC6, PCI-DSS 1 | Listener inventory, segmentation evidence |
| Detection and response | Security operations | All applicable layers | CC7, PCI-DSS 6 | SIEM events, alert rules, response records |
Auditors commonly ask who can pull images, how signatures are verified, how drift from the baseline is detected, and where runtime telemetry is retained. CIS is strong on configuration, but teams still need explicit SBOM retention and provenance-attestation procedures. Use the NIST control families resource to organize those artifacts by control family without treating a framework mapping as proof of implementation.
The evidence template I expect
- Artifact: Policy file, benchmark output, scan report, signature result, or runtime event.
- Owner: The person or team responsible for remediation.
- Frequency: The defined review or execution cadence.
- Retention: The period and storage location for audit and incident use.
- Exception: Business justification, compensating control, expiry, and approver.
- Retest: Verification output showing whether the finding remains open.
A Pentester Verification Checklist With Example Commands
The assessment should be reproducible by another tester. Start with inventory, preserve the outputs, and compare the observed state with the approved architecture:
docker ps -a --no-truncdocker images --digestsdocker infodocker network ls
Look for containers using host networking, privileged mode, unexpected published ports, broad mounts, and images referenced by mutable tags. Inventory isn't the finding by itself. The finding comes from a mismatch between the observed configuration and the authorized design.
Inspect effective settings
docker inspect <container-id>
Review CapAdd, CapDrop, SecurityOpt, NoNewPrivileges, ReadonlyRootfs, resource limits, mounts, network mode, and published ports. A configuration that looks safe in the Dockerfile can become unsafe through a Compose file, Helm chart, or command-line override. Capture the rendered deployment and the runtime inspection together.
Scan both artifacts and source files:
trivy image --severity HIGH,CRITICAL <image>trivy fs .
Verify provenance with the mechanism the organization enforces.
docker trust inspect <image>
For Sigstore deployments, validate the configured Cosign policy against the image digest and registry identity. Don't accept a screenshot of a successful signing command as proof that admission verifies the signature.
Run baseline and runtime tests
Where authorization permits, run Docker Bench for Security:
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock docker/docker-bench-security
Docker Bench is an automated self-assessment script based on CIS Docker Benchmark v1.6.0 and checks dozens of production best practices, as described in the Docker Bench for Security project. Retain the raw output, version, host identity, and documented exceptions. A failed check needs context, but an undocumented exception is an unresolved risk.
Use runtime commands to validate what the workload does, not only what the manifest declares:
docker exec <container-id> ps auxdocker stats --no-streamdocker events --since 10m
Watch for unexpected shell execution, privilege escalation, new mounts, capability changes, daemon-socket access, and outbound connections. Test alerts with an approved benign action, then confirm that the event reaches the SIEM with enough context to investigate.
Classify each issue by exploitability, affected layer, business impact, and compensating control. Retest after remediation, compare the new evidence with the original observation, and export a report mapped to the CIS Docker Benchmark and NIST SP 800-190. A successful assessment leaves an auditable trail, not just a list of scanner findings.
ThreatExploit AI helps MSSPs and security consultancies automate reconnaissance, exploitation, verification, and compliance-mapped reporting across web, network, and cloud environments. Use it to turn Docker assessments into repeatable tests with evidence-backed findings and client-ready outputs, then visit ThreatExploit AI to explore the platform.
