> ## 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.

# Pods Should Not Share Host Namespaces

### More Info:

Verifies no pod sets hostPID, hostIPC or hostNetwork. Sharing a host namespace breaks the isolation boundary between the pod and the node.

### Risk Level

Critical

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. Identify non-compliant Pods (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json | jq -r '
             [ .items[]
             | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | (.spec.nodeName // "") as $node
             | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
             | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
             | (.spec.hostPID // false) as $hostPID
             | (.spec.hostIPC // false) as $hostIPC
             | (.spec.hostNetwork // false) as $hostNet
             | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
               + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
               + (if $node   == ""   then "" else " node=\($node)" end)
               + (if $labels == ""   then "" else " labels=\($labels)" end)
               + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
               + " hostPID=\($hostPID) hostIPC=\($hostIPC) hostNetwork=\($hostNet)"
               + " is_compliant=\(if ($hostPID or $hostIPC or $hostNet) then "false" else "true" end)"
             ][]' | grep 'is_compliant=false'
           ```

        2. For each non-compliant Pod that is controlled by a higher-level object (Deployment, DaemonSet, StatefulSet, Job, etc.), edit the controller manifest to remove host namespace sharing (run on any machine with kubectl access):
           ```bash theme={null}
           # Example for a Deployment
           kubectl -n NAMESPACE edit deployment DEPLOYMENT_NAME
           ```
           In the opened spec, under `spec.template.spec`, ensure:
           ```yaml theme={null}
           hostPID: false        # or remove this line entirely
           hostIPC: false        # or remove this line entirely
           hostNetwork: false    # or remove this line entirely
           ```
           Save and exit; Kubernetes will roll out updated Pods.

        3. For non-compliant standalone Pods (no controller ownerReferences), patch the Pod spec so it no longer shares host namespaces (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl -n NAMESPACE patch pod POD_NAME --type='merge' -p '{
             "spec": {
               "hostPID": false,
               "hostIPC": false,
               "hostNetwork": false
             }
           }'
           ```
           If the Pod definition is created from a manifest you maintain, also update that manifest’s `spec` section in source control to omit these fields or set them to `false`.

        4. If any non-compliant Pods are part of critical EKS add-ons you manage yourself (for example, custom CNI or monitoring agents), review whether they truly require hostPID/hostIPC/hostNetwork. Where feasible, redesign them to use Kubernetes primitives (e.g., downward API, privileges limited to required resources) instead of host namespace sharing, then update their controller manifests as in step 2.

        5. If a Pod genuinely requires a host namespace (for example, a node-level troubleshooting DaemonSet), document the justification, namespace, controller name, and fields used (hostPID/hostIPC/hostNetwork) in your security exceptions register and consider restricting its use to dedicated admin-only namespaces and nodes.

        6. Verify all Pods now comply (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json | jq -r '
             [ .items[]
             | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | (.spec.nodeName // "") as $node
             | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
             | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
             | (.spec.hostPID // false) as $hostPID
             | (.spec.hostIPC // false) as $hostIPC
             | (.spec.hostNetwork // false) as $hostNet
             | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
               + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
               + (if $node   == ""   then "" else " node=\($node)" end)
               + (if $labels == ""   then "" else " labels=\($labels)" end)
               + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
               + " hostPID=\($hostPID) hostIPC=\($hostIPC) hostNetwork=\($hostNet)"
               + " is_compliant=\(if ($hostPID or $hostIPC or $hostNet) then "false" else "true" end)"
             ] as $rows
             | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end' \
           | grep -q 'is_compliant=false' || echo "is_compliant=true"
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        On any machine with `kubectl` access:

        1. Identify non-compliant pods (for context)

        ```bash theme={null}
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.hostPID // false) as $hostPID
          | (.spec.hostIPC // false) as $hostIPC
          | (.spec.hostNetwork // false) as $hostNet
          | select($hostPID or $hostIPC or $hostNet)
          | "ns=\($m.namespace) name=\($m.name) hostPID=\($hostPID) hostIPC=\($hostIPC) hostNetwork=\($hostNet)"
          ][]'
        ```

        2. For each affected pod, edit the owning workload (Deployment, DaemonSet, StatefulSet, etc.) and remove or set the host namespace fields to `false`.

        Example for a Deployment:

        ```bash theme={null}
        kubectl -n NAMESPACE get deploy DEPLOYMENT_NAME -o yaml > deployment-fixed.yaml
        ```

        Edit `deployment-fixed.yaml` so the pod template has:

        ```yaml theme={null}
        spec:
          template:
            spec:
              hostPID: false        # or remove this line entirely
              hostIPC: false        # or remove this line entirely
              hostNetwork: false    # or remove this line entirely
              containers:
              - name: ...
                image: ...
        ```

        Apply the updated manifest:

        ```bash theme={null}
        kubectl apply -f deployment-fixed.yaml
        ```

        Repeat similarly for other controllers:

        ```bash theme={null}
        # DaemonSet
        kubectl -n NAMESPACE get daemonset DAEMONSET_NAME -o yaml > ds-fixed.yaml
        # StatefulSet
        kubectl -n NAMESPACE get statefulset STATEFULSET_NAME -o yaml > sts-fixed.yaml
        # Job / CronJob
        kubectl -n NAMESPACE get job JOB_NAME -o yaml > job-fixed.yaml
        kubectl -n NAMESPACE get cronjob CRONJOB_NAME -o yaml > cj-fixed.yaml
        ```

        Edit each file’s `spec.template.spec` section to remove or set `hostPID`, `hostIPC`, and `hostNetwork` to `false`, then:

        ```bash theme={null}
        kubectl apply -f ds-fixed.yaml
        kubectl apply -f sts-fixed.yaml
        kubectl apply -f job-fixed.yaml
        kubectl apply -f cj-fixed.yaml
        ```

        If a pod is standalone (no controller), recreate it from a manifest without these fields:

        ```bash theme={null}
        kubectl -n NAMESPACE get pod POD_NAME -o yaml > pod-fixed.yaml
        # edit: delete metadata fields like uid, resourceVersion, status, etc.,
        # and ensure spec.hostPID/spec.hostIPC/spec.hostNetwork are absent or false
        kubectl -n NAMESPACE delete pod POD_NAME
        kubectl apply -f pod-fixed.yaml
        ```

        3. Verification (same machine with `kubectl`):

        ```bash theme={null}
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.hostPID // false) as $hostPID
          | (.spec.hostIPC // false) as $hostIPC
          | (.spec.hostNetwork // false) as $hostNet
          | select($hostPID or $hostIPC or $hostNet)
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Remediate CBP C1.2: ensure pods do not share host PID/IPC/Network namespaces.
        #
        # Platform: Amazon EKS
        # Scope: any machine with kubectl access and jq installed
        #
        # Behavior:
        # - Finds *namespaced* workloads (Deployments, StatefulSets, DaemonSets, ReplicaSets, ReplicationControllers, Jobs, CronJobs)
        #   outside kube-system, kube-public, kube-node-lease that set hostPID/hostIPC/hostNetwork=true.
        # - Patches them to set these fields to false at the pod template level.
        # - Does NOT touch standalone Pods (they are usually not long‑lived controllers).
        # - Safe to re-run: patches only set fields explicitly to false.
        # - Ends with the benchmark audit command to verify.

        set -euo pipefail

        # --- configuration -----------------------------------------------------------

        # Namespaces to ignore (system components)
        IGNORED_NAMESPACES=("kube-system" "kube-public" "kube-node-lease")

        # Workload kinds to inspect/patch
        WORKLOAD_KINDS=(
          deployment
          statefulset
          daemonset
          replicaset
          replicationcontroller
          job
          cronjob
        )

        # --- helper functions -------------------------------------------------------

        is_ignored_ns() {
          local ns="$1"
          for n in "${IGNORED_NAMESPACES[@]}"; do
            if [[ "$ns" == "$n" ]]; then
              return 0
            fi
          done
          return 1
        }

        # --- detection & remediation ------------------------------------------------

        echo "Discovering workloads that use hostPID/hostIPC/hostNetwork..."

        for kind in "${WORKLOAD_KINDS[@]}"; do
          # Get all objects of this kind cluster‑wide in JSON
          # We allow failure for kinds that may not exist in some clusters.
          if ! all_json=$(kubectl get "$kind" --all-namespaces -o json 2>/dev/null); then
            continue
          fi

          # Extract a compact list: ns, name, kind, and flags from pod template
          echo "$all_json" | jq -r '
            .items[]?
            | .metadata.namespace as $ns
            | .metadata.name as $name
            | .kind as $kind
            | (.spec.template.spec.hostPID   // false) as $hostPID
            | (.spec.template.spec.hostIPC   // false) as $hostIPC
            | (.spec.template.spec.hostNetwork // false) as $hostNet
            | select($hostPID or $hostIPC or $hostNet)
            | "\($ns) \($name) \($kind) \($hostPID) \($hostIPC) \($hostNet)"
          ' | while read -r ns name kind_read hostPID hostIPC hostNet; do
            # Skip ignored namespaces
            if is_ignored_ns "$ns"; then
              continue
            fi

            echo "Found non-compliant workload: kind=${kind_read} ns=${ns} name=${name} (hostPID=${hostPID}, hostIPC=${hostIPC}, hostNetwork=${hostNet})"

            # Build JSON patch setting any of the three fields that are true to false.
            patch_ops=()
            if [[ "$hostPID" == "true" ]]; then
              patch_ops+=('{"op":"replace","path":"/spec/template/spec/hostPID","value":false}')
            fi
            if [[ "$hostIPC" == "true" ]]; then
              patch_ops+=('{"op":"replace","path":"/spec/template/spec/hostIPC","value":false}')
            fi
            if [[ "$hostNet" == "true" ]]; then
              patch_ops+=('{"op":"replace","path":"/spec/template/spec/hostNetwork","value":false}')
            fi

            # If any of those fields were previously absent and set via defaults,
            # there is nothing to patch; but our selection only included "true".
            if [[ "${#patch_ops[@]}" -eq 0 ]]; then
              continue
            fi

            patch_json=$(printf '[%s]\n' "$(IFS=,; echo "${patch_ops[*]}")")

            echo "Patching ${kind_read}/${ns}/${name} to set hostPID/hostIPC/hostNetwork to false..."
            kubectl patch "$kind" "$name" -n "$ns" --type='json' -p "$patch_json"
          done
        done

        echo "Remediation phase completed."

        # --- verification -----------------------------------------------------------

        echo
        echo "Verifying: running benchmark audit command to confirm compliance..."
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.nodeName // "") as $node
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
          | (.spec.hostPID // false) as $hostPID
          | (.spec.hostIPC // false) as $hostIPC
          | (.spec.hostNetwork // false) as $hostNet
          | "kind=Pod ns=\($m.namespace) name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $node   == ""   then "" else " node=\($node)" end)
            + (if $labels == ""   then "" else " labels=\($labels)" end)
            + (if $own    == null then "" else " owner=\($own.kind)/\($m.namespace)/\($own.name)/\($own.uid)" end)
            + " hostPID=\($hostPID) hostIPC=\($hostIPC) hostNetwork=\($hostNet)"
            + " is_compliant=\(if ($hostPID or $hostIPC or $hostNet) then "false" else "true" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
