Skip to main content

More Info:

Verifies no pod mounts a hostPath volume. hostPath exposes the node filesystem to the pod and can be used to escape to the host.

Risk Level

High

Address

Security

Compliance Standards

  • Cloudanix Best Practice

Triage and Remediation

Remediation

Manual Steps

  1. On any machine with kubectl access, list all pods using hostPath volumes (excluding system namespaces) and note which are controlled by higher-level resources (Deployment/DaemonSet/StatefulSet/Job/etc.):
  2. For each offending pod that is controlled by a workload resource (e.g., Deployment), edit the controller manifest and remove/replace the hostPath volumes. Example for a Deployment:
    In the editor:
    • Under spec.template.spec.volumes, delete any entries containing hostPath: or replace them with emptyDir: {} or a PersistentVolume/PVC reference as appropriate.
    • Under spec.template.spec.containers[].volumeMounts, remove the corresponding name: entries or adjust them to point to the new volume type. Save and exit; Kubernetes will roll out new pods without hostPath.
  3. For pods created directly (no controller) using hostPath, export, modify, and reapply their manifests:
    Edit /tmp/pod-with-hostpath.yaml:
    • Remove the entire metadata: block fields resourceVersion, uid, selfLink, creationTimestamp, status, and any ownerReferences.
    • Under spec.volumes, remove or replace any entries containing hostPath: with emptyDir: {} or a PV/PVC.
    • Update spec.containers[].volumeMounts to remove or point away from those volume names.
    Then delete and recreate the pod:
  4. For workloads that legitimately need node storage, create and use PersistentVolumes and PersistentVolumeClaims instead of hostPath (on any machine with kubectl access). Example (adapt for your case) to create a PVC and reference it from the workload:
    Then in the controller manifest (kubectl -n NAMESPACE edit deployment CONTROLLER_NAME), use:
  5. For any third-party or GKE-managed add-ons that appear to use hostPath, review their documentation and only modify them if they are not required or if the vendor provides a hostPath-free configuration. If you must keep a hostPath-based add-on, document the risk and namespace, labels, and pod names for risk acceptance:
  6. Verification (on any machine with kubectl access): rerun the audit command and confirm there are no lines with is_compliant=false and no hostPaths= fields:
    The cluster is compliant when the output is either is_compliant=true only, or all listed pods show is_compliant=true and no hostPaths=.
On any machine with kubectl access:
  1. Identify offending pods and their owners
For each non‑compliant line, note:
  • ns=<namespace>
  • owner=<Kind>/<namespace>/<name>/... if present; otherwise treat it as a standalone Pod.
  1. Edit the controller manifest to remove hostPath
For a Deployment (example):
Edit /tmp/deploy-no-hostpath.yaml:
  • In spec.template.spec.volumes, delete any entries with hostPath:.
  • In spec.template.spec.containers[].volumeMounts, remove mounts that referenced those hostPath volumes.
  • If needed, add a safer volume type, for example:
Apply the updated manifest:
Repeat the same pattern for other controller types as applicable:
  • ReplicaSet: kubectl -n NAMESPACE get rs NAME -o yaml > /tmp/rs-no-hostpath.yaml
  • StatefulSet: kubectl -n NAMESPACE get sts NAME -o yaml > /tmp/sts-no-hostpath.yaml
  • DaemonSet: kubectl -n NAMESPACE get ds NAME -o yaml > /tmp/ds-no-hostpath.yaml
  • Job/CronJob: kubectl -n NAMESPACE get job|cronjob NAME -o yaml > /tmp/job-no-hostpath.yaml
Then edit to remove hostPath volumes and corresponding mounts, replace with emptyDir, PersistentVolumeClaims, or projected volumes, and:
  1. For standalone Pods (no controller)
Export, edit, and recreate without hostPath:
Edit /tmp/pod-no-hostpath.yaml to:
  • Remove hostPath entries under spec.volumes.
  • Remove corresponding volumeMounts.
  • Optionally add safer volume types as above.
Delete and recreate:
  1. Verification
Run the original audit command and confirm either is_compliant=true only, or that no lines show hostPaths=: