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

# Container Network Interface File Permissions Should Be 600 Or More Restrictive

### More Info:

Verifies that Container Network Interface configuration files have permissions of 600 or more restrictive to prevent tampering with pod networking.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every control plane node, identify the CNI config directory used by kubelet (fallbacks to `/etc/cni/net.d` if not set):

           ```bash theme={null}
           ps -ef | grep kubelet | grep -- --cni-conf-dir || echo "No --cni-conf-dir flag; default is /etc/cni/net.d"
           ```

        2. On every control plane node, set permissions on all CNI config files in the directory (replace `/etc/cni/net.d` if your path is different):

           ```bash theme={null}
           sudo chmod 600 /etc/cni/net.d/*
           ```

        3. On every control plane node, ensure ownership is appropriate (commonly `root:root`; adjust if your environment requires different ownership):

           ```bash theme={null}
           sudo chown root:root /etc/cni/net.d/*
           ```

        4. On every control plane node, if you are using per-network state under `/var/lib/cni/networks`, optionally restrict those files as well (if present):

           ```bash theme={null}
           sudo find /var/lib/cni/networks -type f -exec chmod 600 {} \;
           sudo find /var/lib/cni/networks -type f -exec chown root:root {} \;
           ```

        5. On every control plane node, verify that all CNI configuration and network state files now have permissions `600`:

           ```bash theme={null}
           ps -ef | grep kubelet | grep -- --cni-conf-dir | \
             sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | \
             xargs -I{} find {} -mindepth 1 | \
             xargs --no-run-if-empty stat -c permissions=%a

           find /var/lib/cni/networks -type f 2> /dev/null | \
             xargs --no-run-if-empty stat -c permissions=%a
           ```

           Confirm the output shows only `permissions=600`.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify Container Network Interface file permissions because they are host-level files under `/etc/cni/net.d` (and other CNI paths) on each control plane node. To remediate this finding, adjust permissions directly on those nodes as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Harden CNI configuration and network state file permissions on all control plane nodes.
        # Target: every control plane node (run locally on each node or via SSH/Ansible).
        #
        # Effect:
        # - Sets CNI config files (kubelet --cni-conf-dir, default /etc/cni/net.d) to 600.
        # - Sets CNI network state files under /var/lib/cni/networks to 600.
        # Safe to re-run; only changes file modes.

        set -euo pipefail

        echo "[INFO] Detecting CNI configuration directory from kubelet arguments..."

        # Try to extract --cni-conf-dir from kubelet process; fall back to default if not present.
        CNI_CONF_DIR="$(
          ps -ef | grep kubelet | grep -v grep | \
            sed -n 's%.*--cni-conf-dir[= ]\([^ ]*\).*%\1%p' | head -n1
        )"

        if [[ -z "${CNI_CONF_DIR}" ]]; then
          # Common default used by most distros
          CNI_CONF_DIR="/etc/cni/net.d"
          echo "[INFO] --cni-conf-dir not explicitly set; falling back to default: ${CNI_CONF_DIR}"
        else
          echo "[INFO] Found CNI configuration directory from kubelet: ${CNI_CONF_DIR}"
        fi

        if [[ ! -d "${CNI_CONF_DIR}" ]]; then
          echo "[WARN] CNI configuration directory does not exist: ${CNI_CONF_DIR}"
        else
          echo "[INFO] Setting permissions to 600 for files in ${CNI_CONF_DIR} ..."
          # Only files, not directories; ignore errors if directory is empty.
          find "${CNI_CONF_DIR}" -mindepth 1 -maxdepth 1 -type f -print0 2>/dev/null | \
            xargs -0 --no-run-if-empty chmod 600
        fi

        CNI_STATE_DIR="/var/lib/cni/networks"
        if [[ -d "${CNI_STATE_DIR}" ]]; then
          echo "[INFO] Setting permissions to 600 for CNI state files in ${CNI_STATE_DIR} ..."
          find "${CNI_STATE_DIR}" -type f -print0 2>/dev/null | \
            xargs -0 --no-run-if-empty chmod 600
        else
          echo "[INFO] CNI state directory not present (ok): ${CNI_STATE_DIR}"
        fi

        echo "[INFO] Verifying resulting permissions..."

        # Re-run the benchmark audit commands to confirm.

        echo "[VERIFY] CNI configuration files:"
        ps -ef | grep kubelet | grep -- --cni-conf-dir | \
          sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | \
          xargs -I{} find {} -mindepth 1 2>/dev/null | \
          xargs --no-run-if-empty stat -c '%n permissions=%a'

        echo "[VERIFY] CNI network state files:"
        find /var/lib/cni/networks -type f 2> /dev/null | \
          xargs --no-run-if-empty stat -c '%n permissions=%a'

        echo "[INFO] Check that all listed permissions are 600 or more restrictive (e.g., 600, 400)."
        ```

        Run this script on every control plane node (directly or via your automation tool).
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
