Safeguard
Container Security

Containers Running in Privileged Mode: Risks and Fixes

Docker's --privileged flag strips seccomp, AppArmor, and capability limits in one line. Here's how attackers exploit it, real CVEs, and how to lock it down.

Karan Patel
Cloud Security Engineer
7 min read

One flag turns a sandboxed process into root on the host. Docker's --privileged mode — and its Kubernetes equivalent, securityContext.privileged: true — disables the default seccomp filter, drops AppArmor and SELinux confinement, and hands the container every Linux capability the kernel supports, including CAP_SYS_ADMIN and CAP_SYS_MODULE. It also mounts every host device under /dev straight into the container. Introduced with Docker 0.6 back in 2013 to make Docker-in-Docker possible, the flag has since become a default reach for teams stuck on a permissions error, and it turns up in CI runners, GPU workloads, and legacy monitoring agents across production fleets. The problem is that a privileged container isn't really a container — it's a thin wrapper around full host access. When it's compromised through a vulnerable dependency, an exposed API, or a supply-chain attack, the blast radius is the entire node, not just the workload. Here's what that looks like in practice, and how to close it off.

What Does Running a Container in Privileged Mode Actually Do?

It removes nearly every isolation control Linux gives you, in a single command-line flag. A default Docker container drops most of the roughly 40 Linux capabilities the kernel exposes and keeps a working set of about 14 (CAP_CHOWN, CAP_NET_BIND_SERVICE, and similar). --privileged grants all of them, including CAP_SYS_ADMIN, which the container escape research community half-jokingly calls "the new root," and CAP_SYS_MODULE, which lets a process load arbitrary kernel modules — code that runs at the highest privilege level on the machine. It also disables Docker's default seccomp profile, which normally blocks around 44 system calls (mount, reboot, keyctl, and others) that have no legitimate use inside a container. On top of that, it bind-mounts every device node from the host's /dev directory, meaning a privileged container can read and write raw block devices like /dev/sda directly. In Kubernetes, this same behavior is set per-pod under spec.containers[].securityContext.privileged: true, and it silently overrides namespace-level Pod Security Standards unless a cluster-wide admission control policy explicitly forbids it.

Why Do Privileged Containers Still Show Up in Production?

Because a handful of legitimate workloads historically needed raw host access, and --privileged became the path of least resistance for everything else. Docker-in-Docker setups used for CI/CD pipelines (building container images inside a container job) are the most common legitimate case, along with GPU scheduling agents, some CSI storage drivers, and network plugins like Calico or Cilium that need to manipulate host networking. The trouble is that once a team sees --privileged unblock one of these cases, it gets copy-pasted into Helm charts, Dockerfiles, and Jenkins pipeline templates for services that need none of that access — a logging sidecar, an internal API, a cron job. Palo Alto Networks' Unit 42 has repeatedly flagged this pattern in cloud misconfiguration research, and it's exactly why the CIS Docker Benchmark (control 5.4) and CIS Kubernetes Benchmark (control 5.2.1, "Minimize the admission of privileged containers") both call it out as a top-priority finding rather than a theoretical risk.

What Happens When a Privileged Container Is Compromised?

The compromise stops being a container incident and becomes a full host takeover. The clearest technical proof is CVE-2022-0492, disclosed in March 2022 by Unit 42 researchers Yiqi Sun and Kevin Wang: a five-year-old bug in the Linux cgroups release_agent mechanism that lets a process with CAP_SYS_ADMIN — present by default in privileged containers — write to a cgroup file and get arbitrary code executed on the host as root. No additional exploit chain required; the capability alone was enough. A year earlier, in June 2021, Unit 42 also disclosed Siloscape, the first malware found actively targeting Windows containers specifically to escape into the underlying Kubernetes cluster and deploy a backdoor. And the runc container runtime vulnerability CVE-2019-5736, patched on February 11, 2019, allowed a malicious container to overwrite the host's runc binary and hijack every container subsequently started on that host — a risk that privileged mode makes trivially easier to reach. These aren't edge cases from a lab; they're documented, CVSS-scored vulnerabilities that shipped in patch notes.

How Do Attackers Actually Escape a Privileged Container to the Host?

Most escapes follow one of three well-documented paths, and all three require privileges that only --privileged mode hands out by default. The first is direct device access: with every host device mounted under /dev, an attacker can mount the host's root filesystem (commonly /dev/sda1) from inside the container and read or write any file on the node, including SSH keys and kubelet credentials. The second is the cgroups release_agent technique behind CVE-2022-0492, where a process with CAP_SYS_ADMIN creates a new cgroup, sets release_agent to a script it controls, and triggers it to execute on the host. The third is kernel module loading: CAP_SYS_MODULE lets a compromised container insmod a malicious .ko file, inserting attacker-controlled code directly into the kernel, below the reach of any container runtime or EDR agent watching userspace processes. Each of these takes minutes to execute once initial access is gained — the hard part for an attacker is finding the privileged container in the first place, which is usually the easy part, since privileged workloads are rarely inventoried separately from everything else.

How Can You Detect and Prevent Privileged Containers Before They're Exploited?

Prevention works best as policy enforced at admission time, not as a code review checklist. Kubernetes removed PodSecurityPolicy entirely in v1.25 (released August 2022) in favor of Pod Security Admission, and its restricted and baseline Pod Security Standards profiles both reject privileged: true outright — set the namespace label pod-security.kubernetes.io/enforce=baseline and the API server blocks the pod before it schedules. For clusters still on custom policy engines, OPA Gatekeeper and Kyverno ship out-of-the-box constraint templates (disallow-privileged-containers) that do the same thing declaratively. The NSA and CISA's Kubernetes Hardening Guide, first published August 2021 and updated in March 2022, lists avoiding privileged containers as one of its explicit hardening recommendations, alongside restricting hostPath mounts and disabling hostNetwork. On the detection side, runtime tools like Falco ship default rules that fire specifically on privileged container launches, and image scanners can flag Dockerfiles and manifests containing --privileged or privileged: true before they ever reach a cluster. The gap most teams have isn't the availability of these controls — it's visibility into which of the hundreds of services already running have quietly inherited the flag from a template nobody's revisited since it was written.

How Safeguard Helps

Safeguard closes exactly that visibility gap by treating privileged mode as a first-class supply chain signal, not a buried line in a YAML file. It continuously scans Dockerfiles, Helm charts, Kubernetes manifests, and CI/CD pipeline definitions across every repository in your SCM, flagging --privileged and securityContext.privileged: true at the source — before the image is built or the manifest is applied — so the finding lands in a pull request, not a post-incident forensics report. For workloads already running, Safeguard correlates admission-time configuration against your live cluster inventory to surface every privileged pod, ranks them by exposure (public-facing service, attached secrets, host network access) rather than treating every hit as equally urgent, and maps each finding back to the commit and author that introduced it. Where a legitimate case exists — a Docker-in-Docker CI runner, for instance — Safeguard helps teams replace blanket --privileged access with a scoped set of explicit capabilities (CAP_SYS_ADMIN alone, say, instead of all ~40), closing the gap between "it works" and "it works with the smallest attack surface possible." Combined with Safeguard's broader software supply chain monitoring — dependency provenance, build pipeline integrity, and SBOM tracking — privileged container detection becomes one input into a single risk picture instead of a finding that lives only in a benchmark report nobody reads until an auditor asks for it.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.