Container Network Interface File Permissions Should Be 600
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
- Remediation
Remediation
Manual Steps
-
On every control plane node, identify the CNI config directory used by kubelet (fallbacks to
/etc/cni/net.dif not set):ps -ef | grep kubelet | grep -- --cni-conf-dir || echo "No --cni-conf-dir flag; default is /etc/cni/net.d" -
On every control plane node, set permissions on all CNI config files in the directory (replace
/etc/cni/net.dif your path is different):sudo chmod 600 /etc/cni/net.d/* -
On every control plane node, ensure ownership is appropriate (commonly
root:root; adjust if your environment requires different ownership):sudo chown root:root /etc/cni/net.d/* -
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):sudo find /var/lib/cni/networks -type f -exec chmod 600 {} \;sudo find /var/lib/cni/networks -type f -exec chown root:root {} \; -
On every control plane node, verify that all CNI configuration and network state files now have permissions
600: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=%afind /var/lib/cni/networks -type f 2> /dev/null | \xargs --no-run-if-empty stat -c permissions=%aConfirm the output shows only
permissions=600.
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.
Automation
#!/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).