A privileged container with a host-path mount is not isolated - it is a chroot with networking. The config that disables the boundary is the finding, not the CVE that exploits it.
Container isolation is a runtime property enforced by the orchestrator manifest, not by the image. The Dockerfile defines what process runs inside a container; the pod spec or task definition defines what that process can see, signal, mount, and bind. A single misconfigured field - privileged: true, a host-path volume at /, hostPID enabled - collapses the Linux namespaces and capabilities the entire container model depends on. The misconfiguration is the finding. No CVE is needed to cross the boundary.
Linux containers are not virtual machines. The process boundary rests on three kernel mechanisms: namespaces (pid, net, mnt, ipc, uts) that control visibility into host resources, cgroups that constrain resource consumption, and Linux Security Modules - seccomp, AppArmor, SELinux, and the capability set - that filter syscalls and privilege. Every container runtime enables these by default. Every orchestrator lets the manifest disable them explicitly, one field at a time or all at once.
privileged: true disables all Linux security mechanisms in a single field. The container process is equivalent to root on the host. Docker's --privileged flag and Kubernetes' securityContext.privileged both invoke this path. CAP_SYS_ADMIN is a close second: it grants the ability to mount arbitrary filesystems, call unshare, and nsenter directly into host namespaces. Several documented escape chains require nothing beyond this one capability. A host-path volume mounting /, /etc, or /var/run/docker.sock with write access lets a root-inside-container process modify node cron entries, SSH authorized keys, or issue Docker API calls that spawn a fresh privileged container. hostPID: true shares the host PID namespace - a root process in the container can ptrace or signal every process on the node, including kubelet. hostNetwork: true shares the host network stack, allowing a container to bind node-level ports and sniff inter-pod traffic. An absent or Unconfined seccomp profile does not create an escape on its own but widens the syscall surface that the chains above depend on.
# dangerous: privileged + host-path mount = node takeover path apiVersion: v1 kind: Pod spec: hostPID: true # shares host PID namespace hostNetwork: true # shares host network stack containers: - name: app image: example-app:v1.2 securityContext: privileged: true # disables all namespace / LSM isolation runAsUser: 0 # root inside container volumeMounts: - name: host-root mountPath: /host volumes: - name: host-root hostPath: path: / # entire node filesystem, writable by root above # corrected: drop capabilities, non-root, no host namespaces spec: containers: - securityContext: allowPrivilegeEscalation: false runAsNonRoot: true runAsUser: 10001 capabilities: drop: [ALL] seccompProfile: type: RuntimeDefault volumes: [] # no host-path volumes
The confirming artifact is a parsed field in a manifest - the evidence is a file path, a line number, and the field value. No exploit is sent; no process attempts to cross the boundary during the scan. The parser reads Kubernetes YAML, docker-compose privileged: true, Terraform aws_ecs_task_definition containerDefinitions JSON, and Helm values files. Each source has a different field path but the same confirming logic: dangerous field present, evidence attached, policy violated.
| Config | What it enables | Severity |
|---|---|---|
| privileged: true | Disables all namespace and LSM isolation in one field | Critical |
| CAP_SYS_ADMIN | Mount arbitrary filesystems, nsenter to host namespace, unshare | Critical |
| hostPath: / (writable, root) | Write to node filesystem: cron, SSH keys, kubelet config | Critical |
| hostPID: true | ptrace and signal all node processes including kubelet | High |
| hostNetwork: true | Bind node-level ports, sniff inter-pod traffic | High |
| seccomp: Unconfined | Permits raw syscalls that escape-chain gadgets rely on | Medium |
A disabled seccomp profile in isolation is a medium - it widens the syscall surface but does not hand over the host by itself. Privileged in isolation is critical because it already disables every enforcement layer regardless of what else is set. The dangerous combinations escalate a high to critical: hostPID: true with CAP_SYS_PTRACE is a process-injection path; a writable hostPath: / with runAsUser: 0 is a node-level file-write path that survives a container restart; hostNetwork: true with CAP_NET_ADMIN is traffic interception on the node's physical interfaces. Each combination carries a separate finding with the specific combination named, not a single "container misconfiguration" catch-all.
Remediation does not require pulling the workload. Most cases resolve to a security context addendum in the manifest: drop ALL capabilities and add back only what the process actually needs, set runAsNonRoot: true with an explicit non-zero UID, replace host-path volumes with named or ephemeral volumes, and pin the seccomp profile to RuntimeDefault or a custom allowlist. Each finding carries the manifest file path and line of the offending field alongside the corrected value - so the fix targets the real source, not a category label.
The boundary the container model depends on is either present in the manifest or it is not. IaC parsing makes that a deterministic check - the same manifest field produces the same finding every run, with the file and line attached as proof. Severity you can defend means knowing the difference between a seccomp gap that widens an already-difficult surface and a privileged pod reachable by a low-privilege attacker on the same cluster who can use it as a node-level foothold. One is a cleanup item with a 30-day SLA; the other is a 7-day critical regardless of how internal the workload appears.