Containers running privileged
What does ZopNight detect here?
A privileged container has effectively root on the node: all Linux capabilities, host devices, and the ability to escape the container boundary. ZopNight checks 3 workload kinds. Most workloads that request it do not need it; the few that genuinely do are recognisable.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1726 · RC-1826 · RC-1926 · RC-1727 · RC-1827 · RC-1927 · RC-1728 · RC-1828 · RC-1928 |
| Category | security |
| Severity | critical |
| Metric | none — pure configuration read |
| Source | internal/rules/k8s/container_privileged.go |
Where it applies
What privileged actually grants
securityContext.privileged: true is not a partial elevation. It disables most of the isolation
that makes a container a container: every Linux capability is granted, /dev on the host is
visible, and AppArmor and seccomp profiles do not apply.
A process in a privileged container can mount the host filesystem, load kernel modules and access other containers’ namespaces. Compromising it is equivalent to compromising the node, and by extension every workload scheduled there, plus the kubelet’s credentials.
The workloads that genuinely need it
A short list, and it is worth knowing so this finding is not applied blindly:
- CNI plugins configuring host networking
- CSI drivers mounting volumes into the host mount namespace
- Node-level agents: monitoring, security tooling, log collectors reading host paths
- Anything managing kernel state, such as tuning sysctls at boot
These are almost always DaemonSets shipped by an infrastructure vendor. A privileged application Deployment is a different matter entirely.
Usually it is one capability, not all of them
Most workloads that request privileged actually need a single capability. NET_ADMIN for network
manipulation, SYS_TIME for clock adjustment, SYS_PTRACE for a debugger.
Granting that one capability keeps every other boundary intact:
securityContext: privileged: false capabilities: add: ["NET_ADMIN"]The usual reason a workload is privileged is that somebody hit a permission error, set
privileged: true, and it worked.
Selecting containers with privileged set to true
kubectl get deploy,statefulset,daemonset -A -o json | jq -r ' .items[] | . as $w | .spec.template.spec.containers[] | select(.securityContext.privileged == true) | "\($w.kind) \($w.metadata.namespace)/\($w.metadata.name): \(.name)"'Preventing the class
Pod Security Admission at the baseline level rejects privileged pods at admission time. Applied
as a namespace label, it stops new ones arriving while you work through the existing list.
That matters more than the list itself, because otherwise the backlog refills.