Weaponizing kubectl debug
Why kubectl debug is a privilege escalation path, not just a troubleshooting tool
kubectl debug is for break-glass work. You either attach an ephemeral debugger to a pod that is already running, or you start a node debugger whose profile controls how close you get to the host.
RBAC for kubectl debug access
Use a ClusterRole instead if you must list nodes or create debugger pods across more than one namespace.
1. Ephemeral containers
You must be able to read the target pod and patch its pods/ephemeralcontainers subresource. For an interactive kubectl debug -it session you also need attach access on that pod.
Sample Role for running ephemeral containers for debugging:
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods/ephemeralcontainers"]
verbs: ["patch"]
- apiGroups: [""]
resources: ["pods/attach"]
verbs: ["create", "get"]
Replace <pod-name>, <namespace>, and <container-name> with real values.
kubectl debug -it <pod-name> -n <namespace> --image=busybox:1.36 --target=<container-name>
Without --target, ephemeral container joins the pod’s network namespace but gets its own isolated PID namespace, so you can’t see other containers’ processes.
With --target=<container>, ephemeral container shares that container’s PID namespace, so ps aux shows the target container’s processes. Useful for inspecting what’s actually running inside it.
2. Node debugging
Node debugging still creates a normal Pod object. kubectl fills in the pod spec for you, including host-oriented settings. That generated spec is often very powerful.
For kubectl debug -it you typically need pods/create, get,list on pods, get,list on nodes (to choose a node), and attach on the debugger pod.
The exact mounts and capabilities depend on the debug profile and your server version.
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list"]
- apiGroups: [""]
resources: ["pods/attach"]
verbs: ["create", "get"]
Replace <node-name> with the node you want:
kubectl debug node/<node-name> -it --image=busybox:1.36 --profile=sysadmin
What --profile=sysadmin means
The --profile flag picks a built-in template for the debugger pod. That template sets the security context and related fields. It is not a Linux sysctl profile.
For kubectl debug node, the upstream docs describe the default-style debugger as not privileged, even though it joins the node’s PID, network, and IPC namespaces and mounts /host. In that situation chroot /host can fail, because the process may still lack the privileges chroot needs.
The sysadmin profile is the strongest of the standard presets that kubectl documents (legacy, general, baseline, netadmin, restricted, sysadmin). If you omit --profile, the client default for that flag is legacy. Always confirm the real behavior on your cluster against the official Debugging profiles page.
After kubectl debug node gives you a shell, move into the host root like this:
chroot /host /bin/sh
The node’s root filesystem is usually mounted inside the debugger pod at /host. Running chroot /host /bin/sh makes / point at the host root, so you see the entire host filesystem.
Impact
Ephemeral debug inherits the pod's network namespace, service account, and volume mounts. Node debug mounts the host filesystem at /host, chroot /host gives full host root access.
Mitigation
- Apply the same guardrails to debug flows as you do for privileged or
hostPathpods (PSA, Kyverno, Gatekeeper), includingpods/ephemeralcontainersandpods/createwhen they feed into debug. - Keep
pods/exec,pods/attach, andpods/ephemeralcontainerson tight break-glass roles. Watch audit logs for EphemeralContainer changes and debugger-style pods. - Where you can, run setups where tenants never get anything close to node debug. Turn off ephemeral containers if you are not using them.
Tools
View all tools- • kubectl audit