> ## 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. List all non-system pods that share any host namespace (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'
           ```

        2. For each reported pod, identify whether it is managed by a higher-level controller (Deployment, StatefulSet, DaemonSet, Job, etc.) by reviewing the `owner=` field from the previous output, or by describing it (run on any machine with kubectl access, example namespace/name):
           ```bash theme={null}
           kubectl -n <NAMESPACE> describe pod <POD_NAME>
           ```

        3. If the pod is managed by a controller (preferred approach), edit the controller’s manifest to remove host namespace sharing (run on any machine with kubectl access):
           ```bash theme={null}
           # Example for a Deployment; replace with the actual kind/name/namespace
           kubectl -n <NAMESPACE> edit deployment <DEPLOYMENT_NAME>
           ```
           In the editor, under `spec.template.spec`, ensure:
           ```yaml theme={null}
           hostPID: false      # or remove the line entirely if present
           hostIPC: false      # or remove the line entirely if present
           hostNetwork: false  # or remove the line entirely if present
           ```
           Save and exit; Kubernetes will roll out updated pods.

        4. If the pod is standalone (no controller), delete and recreate it from a corrected manifest (run on any machine with kubectl access):
           ```bash theme={null}
           # Export the existing pod spec
           kubectl -n <NAMESPACE> get pod <POD_NAME> -o yaml > /tmp/<POD_NAME>.yaml
           ```
           Edit `/tmp/<POD_NAME>.yaml` with a text editor:
           * Remove `metadata.resourceVersion`, `metadata.uid`, `metadata.managedFields`, `metadata.creationTimestamp`, `metadata.ownerReferences`, `status`, and other runtime-only fields.
           * Under `spec`, remove or set:
             ```yaml theme={null}
             hostPID: false
             hostIPC: false
             hostNetwork: false
             ```
           Apply the corrected manifest and delete the old pod:
           ```bash theme={null}
           kubectl -n <NAMESPACE> delete pod <POD_NAME>
           kubectl apply -f /tmp/<POD_NAME>.yaml
           ```

        5. For workloads that legitimately require host namespaces (e.g., certain monitoring/telemetry agents), document the justification and ensure they are limited to the minimal namespaces needed and to trusted namespaces/nodes. Consider using dedicated node pools and labels/taints to isolate such pods.

        6. Verify that no non-system pod shares host namespaces (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'
           ```
           Confirm the output is either `is_compliant=true` or shows all remaining non-compliant pods as explicitly accepted exceptions.
      </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. Edit or patch workload manifests (Deployments, DaemonSets, etc.) to remove or disable host namespaces.

        Example manifest snippet (desired state – ensure all three are false or omitted):

        ```yaml theme={null}
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: example
          namespace: default
        spec:
          template:
            spec:
              # Remove these lines entirely, or set them to false
              # hostPID: false
              # hostIPC: false
              # hostNetwork: false
              containers:
              - name: app
                image: your-image
        ```

        Apply updated manifest:

        ```bash theme={null}
        kubectl apply -f path/to/your-workload.yaml
        ```

        3. If you must adjust a naked Pod (not controlled by a higher-level object), recreate it with compliant spec:

        a. Export current spec:

        ```bash theme={null}
        kubectl get pod POD_NAME -n NAMESPACE -o yaml > /tmp/pod-fixed.yaml
        ```

        b. Edit `/tmp/pod-fixed.yaml`: remove `status:` section and remove or set to `false` these fields under `spec`:

        ```yaml theme={null}
        spec:
          hostPID: false       # or delete line
          hostIPC: false       # or delete line
          hostNetwork: false   # or delete line
        ```

        c. Delete and recreate the pod:

        ```bash theme={null}
        kubectl delete pod POD_NAME -n NAMESPACE
        kubectl apply -f /tmp/pod-fixed.yaml
        ```

        4. 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
          | "ns=\($m.namespace) name=\($m.name) hostPID=\($hostPID) hostIPC=\($hostIPC) hostNetwork=\($hostNet)"
          ] as $rows
          | if ($rows | map(select(. | test("hostPID=true|hostIPC=true|hostNetwork=true"))) | length) == 0
            then "is_compliant=true"
            else $rows[]
            end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Remediation: Ensure pods do not share host namespaces (hostPID/hostIPC/hostNetwork)
        # Scope: Any machine with kubectl access to the cluster
        # Requirements: kubectl, jq
        #
        # Behavior:
        # - Finds all non-system pods with hostPID/hostIPC/hostNetwork == true
        # - Patches their parent controller (Deployment/DaemonSet/StatefulSet/ReplicaSet/Job/CronJob)
        #   to set those fields to false (or add them as false if absent)
        # - If a pod has no controller (standalone Pod), it is reported and must be fixed manually
        # - Safe to re-run: patches are idempotent
        # - Verifies at the end using the benchmark audit logic

        set -euo pipefail

        # -------------------------
        # Helper Functions
        # -------------------------

        require_bin() {
          if ! command -v "$1" >/dev/null 2>&1; then
            echo "ERROR: required command '$1' not found in PATH" >&2
            exit 1
          fi
        }

        json_patch_spec_security() {
          # Emit a jsonpatch fragment to ensure spec.template.spec.{hostPID,hostIPC,hostNetwork} are false
          cat <<'EOF'
        [
          {
            "op": "add",
            "path": "/spec/template/spec/hostPID",
            "value": false
          },
          {
            "op": "add",
            "path": "/spec/template/spec/hostIPC",
            "value": false
          },
          {
            "op": "add",
            "path": "/spec/template/spec/hostNetwork",
            "value": false
          }
        ]
        EOF
        }

        json_patch_cronjob() {
          # Emit a jsonpatch fragment to ensure spec.jobTemplate.spec.template.spec.{hostPID,hostIPC,hostNetwork} are false
          cat <<'EOF'
        [
          {
            "op": "add",
            "path": "/spec/jobTemplate/spec/template/spec/hostPID",
            "value": false
          },
          {
            "op": "add",
            "path": "/spec/jobTemplate/spec/template/spec/hostIPC",
            "value": false
          },
          {
            "op": "add",
            "path": "/spec/jobTemplate/spec/template/spec/hostNetwork",
            "value": false
          }
        ]
        EOF
        }

        # -------------------------
        # Preconditions
        # -------------------------

        require_bin kubectl
        require_bin jq

        echo "Discovering pods that share host namespaces (excluding kube-system, kube-public, kube-node-lease)..."

        pods_json="$(kubectl get pods --all-namespaces -o json)"

        # -------------------------
        # Identify non-compliant pods
        # -------------------------

        non_compliant_pods=$(echo "${pods_json}" | jq -r '
          .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | (.spec.hostPID // false) as $hostPID
          | (.spec.hostIPC // false) as $hostIPC
          | (.spec.hostNetwork // false) as $hostNet
          | select($hostPID or $hostIPC or $hostNet)
          | {
              ns: .metadata.namespace,
              name: .metadata.name,
              hostPID: $hostPID,
              hostIPC: $hostIPC,
              hostNet: $hostNet,
              owner: ([ (.metadata.ownerReferences // [])[] | select(.controller) ] | first)
            }
          | @base64
        ')

        if [ -z "${non_compliant_pods}" ]; then
          echo "No non-compliant pods found; cluster already conforms to the requirement."
          exit 0
        fi

        echo "Found non-compliant pods. Processing controllers..."

        # Track standalone pods (no owner) for manual review
        standalone_report=""

        # -------------------------
        # Patch controllers
        # -------------------------

        while IFS= read -r row; do
          [ -z "$row" ] && continue
          pod=$(echo "$row" | base64 --decode)

          ns=$(echo "$pod" | jq -r '.ns')
          name=$(echo "$pod" | jq -r '.name')
          hostPID=$(echo "$pod" | jq -r '.hostPID')
          hostIPC=$(echo "$pod" | jq -r '.hostIPC')
          hostNet=$(echo "$pod" | jq -r '.hostNet')

          owner_kind=$(echo "$pod" | jq -r '.owner.kind // empty')
          owner_name=$(echo "$pod" | jq -r '.owner.name // empty')

          if [ -z "${owner_kind}" ] || [ -z "${owner_name}" ]; then
            standalone_report+=$'\n'"- Pod ${ns}/${name} (hostPID=${hostPID}, hostIPC=${hostIPC}, hostNetwork=${hostNet}) has no controller; fix its manifest or recreate it with host* fields omitted or set to false."
            continue
          fi

          echo "Patching controller ${owner_kind}/${ns}/${owner_name} for pod ${ns}/${name} ..."

          case "${owner_kind}" in
            Deployment|DaemonSet|StatefulSet|ReplicaSet|Job)
              patch_payload="$(json_patch_spec_security)"
              kubectl -n "${ns}" patch "${owner_kind,,}/${owner_name}" --type=json -p "${patch_payload}" >/dev/null
              ;;
            CronJob)
              patch_payload="$(json_patch_cronjob)"
              kubectl -n "${ns}" patch cronjob "${owner_name}" --type=json -p "${patch_payload}" >/dev/null
              ;;
            *)
              echo "WARNING: Unsupported owner kind '${owner_kind}' for pod ${ns}/${name}; skipping automatic fix."
              standalone_report+=$'\n'"- Pod ${ns}/${name} owned by unsupported kind ${owner_kind}; review and set hostPID/hostIPC/hostNetwork to false in its spec."
              ;;
          esac

        done <<< "${non_compliant_pods}"

        if [ -n "${standalone_report}" ]; then
          echo
          echo "Manual review required for the following pods/controllers:"
          echo "${standalone_report}"
          echo
        fi

        # -------------------------
        # Verification
        # -------------------------

        echo "Waiting briefly for controllers to roll out updated pods..."
        sleep 10

        echo "Verifying that no non-system pod shares a host namespace..."

        verify_output=$(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)
          | (.spec.hostPID // false) as $hostPID
          | (.spec.hostIPC // false) as $hostIPC
          | (.spec.hostNetwork // false) as $hostNet
          | select($hostPID or $hostIPC or $hostNet)
          ] | length')

        if [ "${verify_output}" -eq 0 ]; then
          echo "Verification passed: no non-system pods currently share hostPID, hostIPC, or hostNetwork."
          exit 0
        else
          echo "WARNING: Verification detected ${verify_output} non-compliant pod(s) still sharing host namespaces."
          echo "Inspect them with:"
          echo "  kubectl get pods --all-namespaces -o wide | grep -vE 'kube-system|kube-public|kube-node-lease'"
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
