Ensure Container Network Interface File Ownership Is Root
More Info:
Ensure that the Container Network Interface files have ownership set to root:root
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every control plane node, confirm the CNI networks directory and current ownership of its files:
sudo find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c '%n %U:%G' -
If your kubelet uses a different CNI configuration directory, identify it (this does not change anything, just informs you):
ps -ef | grep kubelet | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' -
On every control plane node, change ownership of all existing CNI network files under
/var/lib/cni/networkstoroot:root:sudo chown root:root /var/lib/cni/networks/* -
If there are subdirectories containing files, ensure recursive ownership correction:
sudo chown -R root:root /var/lib/cni/networks -
If your environment uses a different CNI networks path, repeat steps 3–4 with that path instead of
/var/lib/cni/networks, using:sudo chown -R root:root <full-path-to-cni-networks-dir> -
Verification on every control plane node:
find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c %U:%GEnsure that the output shows only
root:root.
Using kubectl
kubectl cannot modify host-level file ownership under /var/lib/cni/networks or any other CNI directories on the node. This finding must be fixed directly on every control plane node via OS-level commands (for example, chown), as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Fix ownership of Container Network Interface files to root:root
# Scope: run on every control plane node
# Safe to re-run; only changes non-root-owned files.
set -euo pipefail
echo "=== Detecting CNI configuration directory from kubelet arguments (if present) ==="
CNI_CONF_DIRS=()
# Try to detect --cni-conf-dir from running kubelet
if pgrep -x kubelet >/dev/null 2>&1; then
DETECTED_DIRS=$(ps -ef | grep kubelet | grep -- --cni-conf-dir \
| sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' || true)
if [ -n "${DETECTED_DIRS}" ]; then
while IFS= read -r d; do
[ -n "$d" ] && CNI_CONF_DIRS+=("$d")
done <<< "${DETECTED_DIRS}"
fi
fi
# Always include /var/lib/cni/networks as per finding
CNI_DATA_DIR="/var/lib/cni/networks"
if [ -d "${CNI_DATA_DIR}" ]; then
CNI_CONF_DIRS+=("${CNI_DATA_DIR}")
fi
# De-duplicate directories
if [ "${#CNI_CONF_DIRS[@]}" -eq 0 ]; then
echo "No CNI directories detected and /var/lib/cni/networks not found; nothing to do."
exit 0
fi
readarray -t CNI_CONF_DIRS < <(printf '%s\n' "${CNI_CONF_DIRS[@]}" | awk '!x[$0]++')
echo "CNI directories to process:"
printf ' %s\n' "${CNI_CONF_DIRS[@]}"
echo "=== Ensuring ownership root:root for CNI files ==="
for dir in "${CNI_CONF_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
echo "Skipping non-existent directory: $dir"
continue
fi
echo "Processing directory: $dir"
# Find files not owned by root:root and fix them
# -print0 handles spaces/newlines in filenames safely
find "$dir" -type f ! -user root -o -type f ! -group root -print0 2>/dev/null \
| while IFS= read -r -d '' file; do
echo " Fixing ownership: $file"
chown root:root "$file"
done
done
echo "=== Verification ==="
# Verification 1: using kubelet --cni-conf-dir (if any)
if pgrep -x kubelet >/dev/null 2>&1; then
CONF_DIR_FROM_KUBELET=$(ps -ef | grep kubelet | grep -- --cni-conf-dir \
| sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' || true)
if [ -n "${CONF_DIR_FROM_KUBELET}" ]; then
echo "--- Ownership under kubelet --cni-conf-dir ---"
echo "${CONF_DIR_FROM_KUBELET}" \
| xargs -I{} find {} -mindepth 1 2>/dev/null \
| xargs --no-run-if-empty stat -c '%n %U:%G'
else
echo "No --cni-conf-dir flag detected in kubelet process for verification."
fi
else
echo "kubelet process not found; skipping kubelet-based verification."
fi
# Verification 2: /var/lib/cni/networks
if [ -d "${CNI_DATA_DIR}" ]; then
echo "--- Ownership under ${CNI_DATA_DIR} ---"
find "${CNI_DATA_DIR}" -type f 2>/dev/null \
| xargs --no-run-if-empty stat -c '%n %U:%G'
else
echo "${CNI_DATA_DIR} not present; skipping data-dir verification."
fi
echo "=== Completed. Confirm all entries above show root:root ==="