Ensure Protect Kernel Defaults Argument Is Enabled
More Info:
Protect tuned kernel parameters from overriding kubelet default kernel parameter values.
Risk Level
High
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)
- 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
Remediation
Manual Steps
-
Edit the Kubelet config file on every worker node
sudo vi /var/lib/kubelet/config.yamlIn the top-level YAML (same level as
kind:/apiVersion:), add or set:protectKernelDefaults: true -
(If also using kubelet flags) Edit the kubelet systemd drop-in on every worker node
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.confIn the
KUBELET_SYSTEM_PODS_ARGS(or theEnvironment=/ExecStart=line that holds kubelet flags), ensure this flag is present (or add it):--protect-kernel-defaults=true -
Reload systemd and restart kubelet on every worker node
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
Verify kubelet is running with protect-kernel-defaults enabled on each worker node
/bin/ps -fC kubelet | grep -- --protect-kernel-defaultsConfirm that the output includes
--protect-kernel-defaults=true.
Using kubectl
kubectl cannot modify kubelet process flags or the kubelet config file on worker nodes, so this setting cannot be fixed via Kubernetes API objects. To remediate, you must change /var/lib/kubelet/config.yaml or the kubelet systemd unit on every worker node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Enable protectKernelDefaults for kubelet on each worker node.
# Run this on every worker node as root.
# Safe to re-run; it will only adjust config if needed.
set -euo pipefail
KUBELET_CONFIG="/var/lib/kubelet/config.yaml"
SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
echo "[*] Ensuring kubelet protectKernelDefaults is enabled..."
fix_config_file() {
if [ ! -f "$KUBELET_CONFIG" ]; then
echo "[-] $KUBELET_CONFIG not found; skipping file-based configuration."
return
fi
if ! command -v python3 >/dev/null 2>&1; then
echo "[-] python3 is required for safe YAML editing; please install it."
return 1
fi
echo "[*] Updating $KUBELET_CONFIG (if needed)..."
python3 << 'PYEOF'
import sys
from pathlib import Path
cfg_path = Path("/var/lib/kubelet/config.yaml")
data = cfg_path.read_text()
# Minimal, structure-preserving update: ensure a top-level line
# 'protectKernelDefaults: true' exists and is set to true.
lines = data.splitlines()
out = []
found = False
for line in lines:
if line.lstrip().startswith("protectKernelDefaults:"):
# Normalize to 'protectKernelDefaults: true'
indent = line[:len(line) - len(line.lstrip())]
out.append(f"{indent}protectKernelDefaults: true")
found = True
else:
out.append(line)
if not found:
# Append at end as a top‑level key
if out and out[-1].strip() != "":
out.append("")
out.append("protectKernelDefaults: true")
new_data = "\n".join(out) + ("\n" if not out or not out[-1].endswith("\n") else "")
if new_data != data:
cfg_path.write_text(new_data)
PYEOF
}
fix_systemd_dropin() {
if [ ! -f "$SYSTEMD_DROPIN" ]; then
echo "[-] $SYSTEMD_DROPIN not found; skipping systemd flag-based configuration."
return
fi
echo "[*] Ensuring --protect-kernel-defaults=true is present in $SYSTEMD_DROPIN..."
# Ensure the KUBELET_SYSTEM_PODS_ARGS variable exists and contains the flag.
if ! grep -q '^Environment="KUBELET_SYSTEM_PODS_ARGS=' "$SYSTEMD_DROPIN"; then
# Add a new Environment line with the flag
echo 'Environment="KUBELET_SYSTEM_PODS_ARGS=--protect-kernel-defaults=true"' >> "$SYSTEMD_DROPIN"
else
# Update existing line to include the flag exactly once
tmp="$(mktemp)"
awk '
/^Environment="KUBELET_SYSTEM_PODS_ARGS=/ {
line=$0
sub(/^Environment="KUBELET_SYSTEM_PODS_ARGS=/,"",line)
sub(/"$/,"",line)
args=line
has_flag=0
n=split(args, a, " ")
out=""
for (i=1;i<=n;i++) {
if (a[i] == "--protect-kernel-defaults=true") has_flag=1
if (a[i] != "") {
if (out=="") out=a[i]; else out=out" "a[i]
}
}
if (!has_flag) {
if (out=="") out="--protect-kernel-defaults=true"
else out=out" --protect-kernel-defaults=true"
}
print "Environment=\"KUBELET_SYSTEM_PODS_ARGS=" out "\""
next
}
{ print }
' "$SYSTEMD_DROPIN" > "$tmp"
mv "$tmp" "$SYSTEMD_DROPIN"
fi
}
# Apply fixes
fix_config_file || true
fix_systemd_dropin || true
echo "[*] Reloading systemd and restarting kubelet..."
systemctl daemon-reload
systemctl restart kubelet.service
echo "[*] Verification: checking kubelet process arguments and config..."
/bin/ps -fC kubelet || { echo "[-] kubelet process not found"; exit 1; }
# Confirm the flag is set on the process OR in the config file
if /bin/ps -fC kubelet | grep -q -- '--protect-kernel-defaults=true'; then
echo "[+] kubelet is running with --protect-kernel-defaults=true"
else
echo "[*] --protect-kernel-defaults flag not visible in process args; checking config file..."
if [ -f "$KUBELET_CONFIG" ] && grep -q '^[[:space:]]*protectKernelDefaults:[[:space:]]*true' "$KUBELET_CONFIG"; then
echo "[+] protectKernelDefaults: true is set in $KUBELET_CONFIG"
else
echo "[-] protectKernelDefaults is not confirmed as enabled; manual review required."
exit 1
fi
fi
echo "[*] Done."