Skip to main content
cd ../config-traps
risk/register/hostpath-mounts-the-docker-sock-escape-hatch.html
Kubernetescritical severityKubernetes

hostPath Mounts: The docker.sock Escape Hatch

Severity
critical
Reviewed
12 Jul 2026
Remediation
~20 minutes
Overview

A hostPath volume mapping /var/run/docker.sock into a pod grants effective node root regardless of container privilege settings. CI runners and monitoring DaemonSets ship this by default while PSA restricted sits unenforced, letting one compromised build job chroot onto the host, steal the kubelet certificate, and reach cluster-admin-equivalent access across every namespace on that node.

Operational summary

At a glance

Symptom
Compromised build job or DaemonSet writes to mounted docker.sock to spawn a privileged container
Likely cause
hostPath volume mounting /var/run/docker.sock with unenforced Pod Security Admission profile
Impact
Node-wide root access, stolen kubelet credentials, cloud IAM metadata, and every pod's service account tokens on that node.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Enforce PSA restricted on build namespaces, block docker.sock hostPath via Kyverno, use kaniko or rootless BuildKit instead.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

A hostPath volume that maps /var/run/docker.sock into a pod. This turns up in CI runner charts (GitLab Runner, Jenkins agent), monitoring DaemonSets that shell out to Docker for metadata, and DinD-based build jobs that need to spin sibling containers without paying the nested-daemon tax.

The Default State

Helm values for these charts ship with volumes: hostPath: path: /var/run/docker.sock and type: "", meaning no path-type validation runs at admission time. The container itself often sets privileged: false, so it looks safe on a security scan. Pod Security Admission, if labelled at all, is frequently left at the privileged profile or unlabelled entirely, because teams disabled the old PodSecurityPolicy during the 1.25 migration and never replaced it. Baseline and restricted PSA profiles explicitly forbid hostPath volumes, but nobody enforces that on the namespace where the runner lives.

The Blast Radius

Socket access is functionally root on the node, regardless of the container’s own capability set. Any process that can write to that socket can run docker run -v /:/host --privileged alpine chroot /host, which lands a shell in the host filesystem. From there it reads the kubelet’s client certificate and kubeconfig under /var/lib/kubelet, pulls the cloud instance metadata endpoint at 169.254.169.254 for the node’s IAM role, and harvests every other pod’s projected service account token sitting in /var/lib/kubelet/pods/*/volumes/kubernetes.io~projected. One compromised build job now has cluster-admin-equivalent reach across every namespace scheduled on that node, and because the daemon is shared, it can spin containers on behalf of any workload the node hosts, not just the one that leaked the credential.

The Lead Mechanic Fix

Enforce PSA restricted on any namespace running build or agent workloads: kubectl label ns ci pod-security.kubernetes.io/enforce=restricted --overwrite. Restricted rejects hostPath volumes outright. Back that with an explicit deny for anyone tempted to relax the label, using a Kyverno ClusterPolicy with a validate rule matching spec.volumes[].hostPath.path against /var/run/docker.sock and /var/lib/docker, set to failureAction: Enforce. Replace DinD build steps with kaniko or rootless BuildKit, which build OCI images without a daemon socket at all. Audit existing exposure with kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.hostPath.path=="/var/run/docker.sock")' and rotate any node that shows a hit, since the kubelet certificate on that node must be treated as burned.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

kubectl label ns ci pod-security.kubernetes.io/enforce=restricted --overwrite
spec.volumes[].hostPath.path
/var/run/docker.sock
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources