> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Minimize Admission Of HostPath Volumes

### More Info:

Do not generally admit containers which make use of hostPath volumes.

### Risk Level

Low

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **List all workloads using `hostPath` volumes**\
           Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get pods -A -o jsonpath='{range .items[?(@.spec.volumes)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}' \
           | while read ns pod; do
               kubectl get pod "$pod" -n "$ns" -o json | \
               jq -r --arg ns "$ns" --arg pod "$pod" '
                 .spec.volumes[]
                 | select(has("hostPath"))
                 | [$ns, $pod, .name, .hostPath.path, (.hostPath.type // "")]
                 | @tsv'
             done | column -t
           ```
           Use this to identify which namespaces and pods currently depend on `hostPath` and why (logging, runtime, node access, etc.).

        2. **Review each namespace’s existing admission controls**\
           Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get ns
           kubectl get psp -A 2>/dev/null || true
           kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration -A
           kubectl get clusterrole,clusterrolebinding -A | grep -i 'pod-security' || true
           ```
           Determine which namespaces host user workloads and whether they already enforce Pod Security Standards or other policies that restrict `hostPath`.

        3. **Decide namespace policy for `hostPath` usage**\
           For each namespace with user workloads:
           * Decide if `hostPath` should be:\
             a) **Fully disallowed**,\
             b) **Allowed only for specific paths** (e.g., `/var/log`, `/var/run`), or\
             c) **Temporarily allowed** while refactoring workloads.\
             Document required exceptions (namespaces, deployments, and exact host paths).

        4. **Implement or tighten policy to restrict `hostPath`**\
           Run on: any machine with kubectl access\
           Examples (adapt to your chosen mechanism; apply only where appropriate):

           * If using Pod Security admission labels:
             ```bash theme={null}
             kubectl label namespace <NAMESPACE> pod-security.kubernetes.io/enforce=restricted --overwrite
             kubectl label namespace <NAMESPACE> pod-security.kubernetes.io/audit=restricted --overwrite
             ```
           * If using Kyverno (example policy – edit namespace selector, allowed paths):
             ```bash theme={null}
             cat << 'EOF' | kubectl apply -f -
             apiVersion: kyverno.io/v1
             kind: ClusterPolicy
             metadata:
               name: restrict-hostpath
             spec:
               validationFailureAction: enforce
               rules:
               - name: disallow-hostpath
                 match:
                   any:
                   - resources:
                       kinds:
                       - Pod
                       namespaces:
                       - "<NAMESPACE>"
                 validate:
                   message: "hostPath volumes are not allowed in this namespace."
                   pattern:
                     spec:
                       volumes:
                       - X(hostPath): "null"
             EOF
             ```

        5. **Refactor or explicitly approve remaining `hostPath` users**\
           For each pod identified in step 1 in namespaces where `hostPath` should be minimized:
           * Prefer alternatives (emptyDir, PVC, projected volumes, CSI drivers) and update manifests:
             ```bash theme={null}
             kubectl -n <NAMESPACE> get deploy <DEPLOYMENT> -o yaml > /tmp/deploy.yaml
             # Edit /tmp/deploy.yaml to remove/replace hostPath volumes
             kubectl -n <NAMESPACE> apply -f /tmp/deploy.yaml
             ```
           * Where `hostPath` is strictly necessary, ensure it is:
             * Limited to the minimal directory.
             * Read-only where possible.
             * Covered by an explicit, narrowly scoped policy exception.

        6. **Verify policies and current workloads**\
           Run on: any machine with kubectl access
           * Confirm namespace labels / policy objects:
             ```bash theme={null}
             kubectl get ns --show-labels
             kubectl get clusterpolicy,policy -A 2>/dev/null || true
             ```
           * Re-run `hostPath` usage discovery to ensure only approved cases remain:
             ```bash theme={null}
             # repeat step 1
             ```
           * Optionally, perform a dry run of a pod using `hostPath` in a locked-down namespace to confirm it is rejected:
             ```bash theme={null}
             cat << 'EOF' | kubectl apply -f - --dry-run=server
             apiVersion: v1
             kind: Pod
             metadata:
               name: test-hostpath
               namespace: <NAMESPACE>
             spec:
               containers:
               - name: c
                 image: busybox
                 command: ["sleep","3600"]
                 volumeMounts:
                 - name: hp
                   mountPath: /host
               volumes:
               - name: hp
                 hostPath:
                   path: /tmp
             EOF
             ```
      </Accordion>

      <Accordion title="Using kubectl">
        ### Using kubectl

        #### 1. List all namespaces to scope your review

        Run on: any machine with kubectl access

        ```bash theme={null}
        kubectl get namespaces
        ```

        You will review each namespace that runs user workloads (typically excluding `kube-system`, `kube-public`, `kube-node-lease`, and provider-specific system namespaces unless you intentionally run user apps there).

        ***

        #### 2. Check for pods using `hostPath` in each namespace

        Run on: any machine with kubectl access

        ```bash theme={null}
        kubectl get pods -A -o jsonpath='{range .items[?(@.spec.volumes)]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{range .spec.volumes[?(@.hostPath)]}{"  volume: "}{.name}{" hostPath: "}{.hostPath.path}{"\n"}{end}{"---\n"}{end}'
        ```

        Indications of a problem:

        * Any pod in a user-workload namespace shows `volume: ... hostPath: /some/path`.
        * Especially concerning paths: `/var/run`, `/var/run/docker.sock`, `/`, `/var/lib/kubelet`, `/etc`, `/var/lib/docker`, or other sensitive host directories.

        To drill into a specific namespace:

        ```bash theme={null}
        NAMESPACE=your-namespace
        kubectl get pods -n "$NAMESPACE" -o yaml | grep -A5 "hostPath:"
        ```

        ***

        #### 3. Identify which controllers define those pods

        Use labels or ownerReferences to find the workload owning a pod that uses `hostPath`.

        Example (replace names as needed):

        ```bash theme={null}
        kubectl get pod -n your-namespace pod-name -o yaml
        ```

        Look under `.metadata.ownerReferences` for `kind` (`Deployment`, `DaemonSet`, `StatefulSet`, `Job`, etc.), then inspect that controller:

        ```bash theme={null}
        kubectl get deployment -n your-namespace deployment-name -o yaml | grep -A8 "hostPath:"
        kubectl get daemonset -n your-namespace ds-name -o yaml | grep -A8 "hostPath:"
        kubectl get statefulset -n your-namespace sts-name -o yaml | grep -A8 "hostPath:"
        ```

        Indications of a problem:

        * Any user-managed controller spec includes `hostPath:` under `.spec.template.spec.volumes`.

        ***

        #### 4. Check for PodSecurity or admission controls that restrict `hostPath`

        ##### 4.1 Pod Security Admission (PSA) labels on namespaces

        ```bash theme={null}
        kubectl get ns --show-labels
        ```

        Look for labels like:

        * `pod-security.kubernetes.io/enforce`
        * `pod-security.kubernetes.io/audit`
        * `pod-security.kubernetes.io/warn`

        Indications of a problem:

        * User-workload namespaces have no Pod Security labels, or:
        * They are set to profiles (`baseline` or `privileged`) that allow broad `hostPath` usage when your policy should be more restrictive (e.g., targeting `restricted` and specific allowed host paths).

        ##### 4.2 PodSecurityPolicy (legacy, if still present)

        ```bash theme={null}
        kubectl get psp
        kubectl get psp -o yaml
        ```

        In PSP definitions, inspect:

        ```bash theme={null}
        kubectl get psp psp-name -o yaml | grep -A15 "hostPath"
        ```

        Indications of a problem:

        * `volumes` allows `hostPath` and:
          * `.spec.allowedHostPaths` is empty, or
          * `pathPrefix: /` or other very broad prefixes without `readOnly: true` where appropriate.
        * PSPs with broad `hostPath` allowances are bound to service accounts used in user-workload namespaces.

        To see which service accounts use a PSP (RBAC binding example):

        ```bash theme={null}
        kubectl get clusterrolebindings.rbac.authorization.k8s.io -o yaml | grep -B3 -A6 "kind: PodSecurityPolicy"
        kubectl get rolebindings.rbac.authorization.k8s.io -A -o yaml | grep -B3 -A6 "kind: PodSecurityPolicy"
        ```

        ***

        #### 5. Check for validating/mutating admission webhooks related to `hostPath`

        ```bash theme={null}
        kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io -o yaml
        kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io -o yaml
        ```

        Search for `hostPath` in webhook configs and related CRDs/policies:

        ```bash theme={null}
        kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations -o yaml | grep -i "hostPath" -n
        ```

        Indications of a problem:

        * No admission webhooks or policies mention `hostPath` while your security model expects centralized enforcement (e.g., Kyverno, OPA Gatekeeper) to restrict or forbid `hostPath`.
        * Policies exist but are in `audit`/`warn` mode only, not `enforce` for hostPath usage.

        ***

        #### 6. If using common policy engines, surface hostPath-related rules

        Examples (run only if the CRDs exist):

        **Kyverno:**

        ```bash theme={null}
        kubectl get clusterpolicy,policy -A -o yaml | grep -i -n "hostPath"
        ```

        **Gatekeeper (OPA):**

        ```bash theme={null}
        kubectl get k8sconstraints,configs,constrainttemplates -A -o yaml | grep -i -n "hostPath"
        ```

        Indications of a problem:

        * No constraints/policies reference `hostPath` at all.
        * Constraints exist but target only limited namespaces, leaving user-workload namespaces unprotected.

        ***

        #### 7. What you decide from the review (human judgement required)

        Based on the above data, you must decide:

        * Which `hostPath` usages are strictly required for functionality and acceptable by policy.
        * Where you should:
          * Remove `hostPath` entirely,
          * Replace it with a safer volume type (e.g., `emptyDir`, PVC),
          * Or constrain it via namespace policies/Pod Security/admission controls to a small set of approved paths and workloads.

        kubectl surfaces the current state; it does not decide or apply the correct restriction policy automatically.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Report namespaces and workloads that use hostPath volumes, and namespaces
        # that do NOT have a policy restricting hostPath (PodSecurity or PSP-like).

        set -euo pipefail

        echo "=== 1) Namespaces with workloads using hostPath volumes ==="
        echo

        # This lists all pods with a hostPath volume and shows the namespace, pod,
        # and the volume's path(s).
        kubectl get pods --all-namespaces -o json \
          | jq -r '
            .items[]
            | . as $pod
            | ($pod.spec.volumes // [])
            | map(select(.hostPath != null))[]
            | "\($pod.metadata.namespace)\t\($pod.metadata.name)\t\(.name)\t\(.hostPath.path)"
          ' 2>/dev/null \
          | sort \
          | awk 'BEGIN{print "NAMESPACE\tPOD\tVOLUME_NAME\tHOSTPATH_PATH"}1'

        echo
        echo "=== 2) Namespaces with PodSecurity Admission labels (v1.25+ clusters) ==="
        echo "# Look for namespaces that allow privileged / unrestricted hostPath usage."
        echo "# Commonly concerning labels (per namespace):"
        echo "#   pod-security.kubernetes.io/enforce"
        echo "#   pod-security.kubernetes.io/audit"
        echo "#   pod-security.kubernetes.io/warn"
        echo

        kubectl get ns --show-labels

        echo
        echo "=== 3) Namespaces and their PodSecurity levels (simplified view) ==="
        echo "# This extracts key PodSecurity labels; missing or 'privileged' levels are higher risk."
        echo

        kubectl get ns -o json \
          | jq -r '
            .items[]
            | [
                .metadata.name,
                (.metadata.labels["pod-security.kubernetes.io/enforce"] // "<none>"),
                (.metadata.labels["pod-security.kubernetes.io/audit"] // "<none>"),
                (.metadata.labels["pod-security.kubernetes.io/warn"] // "<none>")
              ]
            | @tsv
          ' \
          | awk 'BEGIN{print "NAMESPACE\tENFORCE\tAUDIT\tWARN"}1' \
          | column -t

        echo
        echo "=== 4) Legacy PodSecurityPolicy (if present) and hostPath rules ==="
        echo "# If PSP is enabled (older clusters / distributions), inspect hostPath controls."
        echo "# Fields of interest in each PSP:"
        echo "#   spec.allowedHostPaths"
        echo "#   spec.volumes (whether hostPath is allowed at all)"
        echo

        if kubectl api-resources 2>/dev/null | grep -q '^podsecuritypolicies'; then
          kubectl get podsecuritypolicies.policy -o json \
            | jq -r '
              .items[]
              | [
                  .metadata.name,
                  (if (.spec.volumes // []) | index("hostPath") then "hostPath-ALLOWED" else "hostPath-NOT-ALLOWED" end),
                  (if (.spec.allowedHostPaths // []) | length > 0
                     then (.spec.allowedHostPaths | map(.pathPrefix + " (readOnly=" + (if .readOnly then "true" else "false" end) + ")") | join(", "))
                     else "<no allowedHostPaths restrictions>"
                   end)
                ]
              | @tsv
            ' \
            | awk 'BEGIN{print "PSP\tHOSTPATH_STATUS\tALLOWED_HOSTPATHS"}1' \
            | column -t
        else
          echo "No PodSecurityPolicy API detected in this cluster."
        fi

        echo
        echo "=== Interpretation / What indicates a problem? ==="
        echo
        cat <<'EOF'
        Problem indicators to review manually:

        1) From section (1):
           - Any pod listed there is using a hostPath volume.
           - Focus on:
             * User / application namespaces (not core system namespaces like kube-system).
             * hostPath paths that expose the node filesystem widely, such as:
               /, /root, /var, /etc, /usr, /boot, /dev, /var/run/docker.sock, /run/containerd, etc.
           - These should be justified by a clear operational need and additional controls.

        2) From sections (2) and (3) – PodSecurity Admission:
           - Namespaces with missing PodSecurity labels or labels set to 'privileged'
             effectively allow unrestricted hostPath usage (among other things).
           - Namespaces where:
               ENFORCE is "<none>" or "privileged"
             are higher risk and should be reviewed. Consider moving them to 'baseline' or 'restricted'
             and explicitly allowing hostPath only where required.

        3) From section (4) – PodSecurityPolicy (if in use):
           - PSPs that:
               * Include "hostPath" in spec.volumes
               * AND have spec.allowedHostPaths empty or overly broad (e.g. "/")
             allow broad hostPath usage.
           - PSPs bound to user/application namespaces with such broad hostPath configuration
             should be reviewed and constrained, or replaced with stricter policies.

        This script does NOT change anything; it only surfaces where hostPath is used
        and whether namespace-level or PSP-level controls are in place. Use this output
        to decide where to add or tighten policies that restrict hostPath admission.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
