Skip to main content

Ensure Kubeconfig File Permissions Are Set Restrictive

More Info:

Ensure that the kubelet.conf file has permissions of 644 or more restrictive

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CIS EKS
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, check the current permissions of the kubeconfig file:

    stat -c permissions=%a /etc/kubernetes/kubelet.conf
  2. If the permissions are more permissive than 644 (e.g., 664, 666, 600 is fine), set them to 644:

    chmod 644 /etc/kubernetes/kubelet.conf
  3. Confirm the file is owned by the appropriate user and group (typically root:root). If needed, correct it:

    chown root:root /etc/kubernetes/kubelet.conf
  4. Re-verify that the permissions are now 644 or more restrictive:

    stat -c permissions=%a /etc/kubernetes/kubelet.conf
Using kubectl

kubectl cannot modify file permissions on worker node hosts, including /etc/kubernetes/kubelet.conf. This finding must be remediated directly on each worker node’s filesystem (host-level configuration); follow the Manual Steps section on those nodes to apply the fix.

Automation
#!/usr/bin/env bash
#
# Purpose: Ensure /etc/kubernetes/kubelet.conf permissions are 644 or more restrictive
# Scope: Run on every worker node (safe to re-run; idempotent)

set -euo pipefail

KUBECONFIG_PATH="/etc/kubernetes/kubelet.conf"
DESIRED_MODE="644"

echo "=== Kubelet kubeconfig permissions hardening ==="

if [ ! -e "$KUBECONFIG_PATH" ]; then
echo "File not found: $KUBECONFIG_PATH"
echo "Nothing to change on this node."
exit 0
fi

# Get current file mode (numeric, e.g., 600, 644)
CURRENT_MODE="$(stat -c '%a' "$KUBECONFIG_PATH")"

echo "Current permissions on $KUBECONFIG_PATH: $CURRENT_MODE"
echo "Desired minimum permissions: $DESIRED_MODE"

# Normalize to 3-digit modes for comparison
pad_mode() {
local m="$1"
printf "%03d" "$m"
}

CMODE="$(pad_mode "$CURRENT_MODE")"
DMODE="$(pad_mode "$DESIRED_MODE")"

# If current mode is already equal or more restrictive than 644, no change.
# "More restrictive" here means:
# - owner perms <= 6
# - group perms <= 4
# - other perms <= 4
# We enforce that, and then set to 644 if it's more permissive than that.
OWNER=${CMODE:0:1}
GROUP=${CMODE:1:1}
OTHER=${CMODE:2:1}

CHANGE_NEEDED=false

# If any class has permissions greater than allowed by 644, we must change.
if [ "$OWNER" -gt "${DMODE:0:1}" ] || \
[ "$GROUP" -gt "${DMODE:1:1}" ] || \
[ "$OTHER" -gt "${DMODE:2:1}" ]; then
CHANGE_NEEDED=true
fi

if ! $CHANGE_NEEDED; then
echo "Permissions are already 644 or more restrictive. No change required."
else
echo "Updating permissions on $KUBECONFIG_PATH to $DESIRED_MODE"
chmod "$DESIRED_MODE" "$KUBECONFIG_PATH"
fi

# Verification (same logic as audit, per node)
echo "=== Verification ==="
/bin/sh -c "if test -e '$KUBECONFIG_PATH'; then stat -c permissions=%a '$KUBECONFIG_PATH'; fi"

Additional Reading: