Skip to main content

Minimize The Admission Of HostPath Volumes

More Info:

hostPath volumes mount node filesystem paths into containers, enabling access to sensitive host files and escape. Restrict their admission.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Identify current use of hostPath volumes across the cluster

    • Run on: any machine with kubectl access
    • Command:
      kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{range .spec.volumes[?(@.hostPath)]}{" hostPath: "}{.hostPath.path}{"\n"}{end}{end}' | grep -B1 'hostPath' || echo "No hostPath volumes found"
    • Review which namespaces and pods are using hostPath, and whether they are system components (e.g., in kube-system) or user workloads.
  2. Determine which namespaces require protection (user workloads)

    • Run on: any machine with kubectl access
    • Command to list namespaces:
      kubectl get namespaces
    • Classify namespaces into:
      • System/control-plane (e.g., kube-system, kube-node-lease, kube-public)
      • Add-on/infra namespaces where hostPath may be intentionally required
      • User workload namespaces (targets for strong restriction)
  3. Design the admission policy for hostPath in user namespaces

    • Decide, per user namespace, whether:
      • hostPath should be completely disallowed, or
      • Only specific, narrowly scoped paths are allowed (e.g., a CSI driver)
    • If using an admission controller framework (e.g., ValidatingAdmissionPolicy, Kyverno, Gatekeeper), select the mechanism you will use to enforce hostPath restrictions in those namespaces.
  4. Implement or update policies to restrict hostPath in user namespaces

    • Run on: any machine with kubectl access
    • Example: create a strict ValidatingAdmissionPolicy that denies all hostPath volumes in selected namespaces (adjust namespaces as needed):
      cat << 'EOF' | kubectl apply -f -
      apiVersion: admissionregistration.k8s.io/v1
      kind: ValidatingAdmissionPolicy
      metadata:
      name: deny-hostpath-volumes
      spec:
      failurePolicy: Fail
      matchConstraints:
      resourceRules:
      - apiGroups: [""]
      apiVersions: ["v1"]
      operations: ["CREATE", "UPDATE"]
      resources: ["pods"]
      validations:
      - expression: "!(has(object.spec.volumes) && object.spec.volumes.exists(v, has(v.hostPath)))"
      message: "hostPath volumes are not allowed in this cluster/namespace."
      ---
      apiVersion: admissionregistration.k8s.io/v1
      kind: ValidatingAdmissionPolicyBinding
      metadata:
      name: deny-hostpath-volumes-binding
      spec:
      policyName: deny-hostpath-volumes
      validationActions: [ "Deny" ]
      matchResources:
      namespaceSelector:
      matchExpressions:
      - key: kubernetes.io/metadata.name
      operator: In
      values:
      - user-namespace-1
      - user-namespace-2
      EOF
    • If you must allow specific hostPath paths, adjust the expression to allow only those paths instead of denying all hostPath.
  5. Test enforcement and handle existing workloads

    • Run on: any machine with kubectl access
    • Try to deploy a test pod with a hostPath volume into a protected namespace and confirm it is rejected:
      cat << 'EOF' | kubectl apply -f -
      apiVersion: v1
      kind: Pod
      metadata:
      name: hostpath-test-deny
      namespace: user-namespace-1
      spec:
      containers:
      - name: test
      image: busybox
      command: ["sleep", "3600"]
      volumeMounts:
      - name: hp
      mountPath: /mnt
      volumes:
      - name: hp
      hostPath:
      path: /tmp
      EOF
    • For existing pods using hostPath in user namespaces, review whether they are justified; if not, plan to:
      • Update the workloads to remove hostPath, then
      • Redeploy them so that policy is applied on the next create/update.
  6. Re-verify cluster state after changes

    • Run on: any machine with kubectl access
    • Confirm no unintended hostPath use remains in user namespaces:
      kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{range .spec.volumes[?(@.hostPath)]}{" hostPath: "}{.hostPath.path}{"\n"}{end}{end}' | grep -B1 'hostPath' || echo "No hostPath volumes found"
    • Confirm the admission policy objects are present and active:
      kubectl get validatingadmissionpolicies
      kubectl get validatingadmissionpolicybindings
Using kubectl
# 1) List all namespaces that may need policy
# Run on: any machine with kubectl access
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'

Look for all namespaces that host user workloads (typically everything except kube-*, kubernetes-dashboard, istio-system, etc., depending on your environment). Those are the ones that must have a restriction policy.


# 2) Check for Pods currently using hostPath volumes (cluster-wide)
# Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{range .spec.volumes[*]}{" volume: "}{.name}{" type: "}{.hostPath.path}{"\n"}{end}{"---\n"}{end}' 2>/dev/null | grep hostPath -B1

Problem indication:

  • Any line showing hostPath.path (e.g. /var/run/docker.sock, /, /var/lib/kubelet, /etc, etc.) is a Pod that mounts the node filesystem.
  • Each such Pod must be manually reviewed for necessity and scope of the hostPath.

# 3) For a specific namespace, list only Pods with hostPath
# Replace <namespace>
kubectl get pod -n <namespace> -o json | \
jq -r '.items[] | select(.spec.volumes[]? | has("hostPath")) |
.metadata.name as $p |
.spec.volumes[]? |
select(has("hostPath")) |
"\($p) \t volume=\(.name) \t path=\(.hostPath.path)"'

Problem indication:

  • Any user workload namespace with Pods listed here is using hostPath.
  • Broad or sensitive paths (like /, /var, /etc, /var/lib, /var/run) are higher risk.

# 4) Inspect one Pod’s full spec to understand why hostPath is used
# Replace <namespace> and <pod>
kubectl get pod -n <namespace> <pod> -o yaml

Problem indication:

  • .spec.volumes[*].hostPath.path mounted with hostPath.type: "" or Directory without constraints.
  • Combined with securityContext.privileged: true, allowPrivilegeEscalation: true, or runAsUser: 0 indicates high breakout risk.

# 5) Check for existing admission policies that mention hostPath (PodSecurityPolicies, if present)
kubectl get podsecuritypolicies.policy -o yaml 2>/dev/null | \
grep -nE 'hostPath|volumes' -n || echo "No PodSecurityPolicies or no hostPath references found"

Problem indication:

  • Absence of PSPs (on clusters that still support them) or PSPs that allow hostPath volumes without restriction in namespaces where you found hostPath Pods.

# 6) Check namespace-level Pod Security admission (if enabled in the cluster)
# Replace <namespace>
kubectl get ns <namespace> -o yaml | grep -i 'pod-security'

Problem indication:

  • For user namespaces, labels like pod-security.kubernetes.io/enforce: privileged (or no labels at all) combined with hostPath usage means there is no baseline/restricted control to constrain such volumes.

# 7) Check Validating/MutatingWebhookConfigurations for policies handling hostPath
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations -o yaml 2>/dev/null | \
grep -n 'hostPath' -n || echo "No admission webhooks explicitly referencing hostPath found"

Problem indication:

  • No admission webhooks addressing hostPath in a cluster where you depend on external policy (OPA Gatekeeper, Kyverno, etc.) to restrict such volumes.

Use these commands to:

  • Enumerate where hostPath is used.
  • Determine which namespaces run hostPath workloads.
  • Verify whether any admission control mechanism currently restricts hostPath. Human review is required to decide which hostPath uses are justified and what policies to apply to each namespace.
Automation
#!/usr/bin/env bash
# Report use of hostPath volumes across all namespaces
# Run on: any machine with kubectl access and correct KUBECONFIG

set -euo pipefail

echo "Scanning all pods for hostPath volume usage..."
echo

# 1) High‑level summary: which pods use hostPath and how many
echo "=== Summary of pods using hostPath volumes ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
hostPaths: (
[.spec.volumes[]
| select(.hostPath != null)
| {name, path: .hostPath.path, type: (.hostPath.type // "")}
] // []
)
}
| select(.hostPaths | length > 0)
| .ns + "\t" + .pod + "\t" + ( (.hostPaths | length) | tostring )
' \
| awk 'BEGIN { print "NAMESPACE\tPOD\tHOSTPATH_VOLUME_COUNT" }1'
echo

# 2) Detailed report: each hostPath volume with path/type and pod SA
echo "=== Detailed hostPath usage (one line per hostPath volume) ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| ($pod.spec.volumes // [])
| map(select(.hostPath != null))
| .[]
| [
$pod.metadata.namespace,
$pod.metadata.name,
($pod.spec.serviceAccountName // "default"),
.name,
.hostPath.path,
(.hostPath.type // "")
]
| @tsv
' \
| awk '
BEGIN {
OFS="\t";
print "NAMESPACE","POD","SERVICEACCOUNT","VOLUME_NAME","HOSTPATH_PATH","HOSTPATH_TYPE"
}
{ print }
'
echo

# 3) Optional: filter out known system namespaces (tune as needed)
echo "=== Non-system namespaces using hostPath (candidate review targets) ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| select(.metadata.namespace
| IN("kube-system","kube-public","kube-node-lease") | not)
| . as $pod
| ($pod.spec.volumes // [])
| map(select(.hostPath != null))
| .[]
| [
$pod.metadata.namespace,
$pod.metadata.name,
($pod.spec.serviceAccountName // "default"),
.name,
.hostPath.path,
(.hostPath.type // "")
]
| @tsv
' \
| awk '
BEGIN {
OFS="\t";
print "NAMESPACE","POD","SERVICEACCOUNT","VOLUME_NAME","HOSTPATH_PATH","HOSTPATH_TYPE"
}
{ print }
'
echo "Scan complete."

How to interpret the output

  • Any line in the summaries indicates a pod that is using a hostPath volume.
  • Focus review on:
    • Non‑system namespaces (third section).
    • Sensitive paths (examples: /, /var/run, /var/lib/kubelet, /etc, /var/lib/docker, /var/run/docker.sock, /run/containerd, /var/lib/containerd, /host, /proc, /sys).
    • Pods running under broadly scoped or shared service accounts.
  • Pods in user/workload namespaces using hostPath are candidates for:
    • Refactoring to use PVCs or other volume types.
    • Being constrained by admission policy (e.g., Pod Security / ValidatingAdmissionPolicy / external admission controllers) to prevent or tightly control hostPath usage.