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

# Ensure Container Network Interface File Permissions Are Restrictive

### More Info:

Ensure that the Container Network Interface files have permissions of 644 or more restrictive.

### 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 directory where CNI configuration files are stored (from the kubelet flag, if present):
           ```bash theme={null}
           ps -ef | grep kubelet | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%'
           ```
           If this prints nothing, use the default `/etc/cni/net.d` (or your known CNI conf directory).

        2. On every control plane node, set permissions on all CNI configuration files in the CNI conf directory to `644`:
           ```bash theme={null}
           CNI_CONF_DIR=/etc/cni/net.d
           find "$CNI_CONF_DIR" -type f -exec chmod 644 {} \;
           ```

        3. On every control plane node, set permissions on all CNI state/network files under `/var/lib/cni/networks` to `644`:
           ```bash theme={null}
           find /var/lib/cni/networks -type f 2>/dev/null -exec chmod 644 {} \;
           ```

        4. (Optional hardening) On every control plane node, restrict directory execute/search permissions so only root can traverse:
           ```bash theme={null}
           chmod 755 /etc/cni /etc/cni/net.d 2>/dev/null || true
           chmod 755 /var/lib/cni /var/lib/cni/networks 2>/dev/null || true
           ```

        5. Verification on every control plane node:
           ```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 that all reported permissions are `644` or a more restrictive value (e.g., `640`, `600`).
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify file permissions on the node filesystem, including `/var/lib/cni/networks` or any CNI configuration directories. To remediate this finding, you must change permissions directly on every control plane node’s host OS; see the Manual Steps section for the required SSH-based commands.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose: Ensure Container Network Interface files have permissions 644 or more restrictive.
        # Scope:   Run on every control plane node.
        # Impact:  None on running processes; only file mode changes under CNI dirs.

        set -euo pipefail

        # Directories to check/fix
        CNI_CONF_DIRS=()
        CNI_NET_DIRS=("/var/lib/cni/networks")

        echo "=== Detecting CNI configuration directories from kubelet arguments (if any) ==="
        if pgrep -x kubelet >/dev/null 2>&1; then
          # Extract any --cni-conf-dir values from kubelet command line
          while read -r dir; do
            [ -n "$dir" ] && CNI_CONF_DIRS+=("$dir")
          done < <(ps -ef | grep kubelet | grep -- '--cni-conf-dir' | \
                   sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | sort -u)
        else
          echo "kubelet process not found; skipping kubelet-based CNI config detection."
        fi

        # De-duplicate all directories
        uniq_dirs() {
          awk '!x[$0]++'
        }

        ALL_DIRS=()
        for d in "${CNI_CONF_DIRS[@]}" "${CNI_NET_DIRS[@]}"; do
          [ -n "$d" ] && ALL_DIRS+=("$d")
        done
        # Print unique, existing directories
        UNIQ_EXISTING_DIRS=()
        printf '%s\n' "${ALL_DIRS[@]}" 2>/dev/null | uniq_dirs | while read -r d; do
          if [ -d "$d" ]; then
            UNIQ_EXISTING_DIRS+=("$d")
          else
            echo "Note: directory '$d' does not exist; skipping."
          fi
        done

        # Because arrays aren’t preserved across the while subshell, rebuild from stdout
        mapfile -t TARGET_DIRS < <(printf '%s\n' "${ALL_DIRS[@]}" 2>/dev/null | uniq_dirs | while read -r d; do [ -d "$d" ] && echo "$d"; done)

        echo "=== Directories to process ==="
        if [ "${#TARGET_DIRS[@]}" -eq 0 ]; then
          echo "No existing CNI directories found; nothing to change."
          exit 0
        fi
        printf '  %s\n' "${TARGET_DIRS[@]}"

        echo "=== Fixing permissions to 0644 where more permissive ==="
        for dir in "${TARGET_DIRS[@]}"; do
          echo "Processing: $dir"
          # Find files with permissions more permissive than 644 (i.e., world or group write/execute)
          # and set them to 644. This is idempotent: files already at 644 or stricter remain unchanged.
          find "$dir" -type f 2>/dev/null | while read -r f; do
            # Get current numeric permissions
            perm=$(stat -c '%a' "$f" 2>/dev/null || echo "")
            [ -z "$perm" ] && continue

            # Normalize to three digits if shorter
            perm=$(printf '%03d' "$perm")

            # Extract owner/group/other bits
            o=${perm:0:1}
            g=${perm:1:1}
            w=${perm:2:1}

            # Determine if more permissive than 644 (i.e. any write/exec beyond 644)
            # 644 = owner:6 (rw-), group:4 (r--), other:4 (r--)
            change=false
            # If owner has exec (1) or setuid bits we leave; we only tighten group/other writes/exec.
            # If group >4 or other >4 then it's more permissive.
            if [ "$g" -gt 4 ] || [ "$w" -gt 4 ]; then
              change=true
            fi

            if $change; then
              chmod 644 "$f"
            fi
          done
        done

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

        echo "--- From /var/lib/cni/networks ---"
        find /var/lib/cni/networks -type f 2>/dev/null | \
          xargs --no-run-if-empty stat -c '%n permissions=%a' || true

        echo "=== Completed. Re-run this script at any time; it is idempotent. ==="
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/cluster-administration/networking/](https://kubernetes.io/docs/concepts/cluster-administration/networking/)
