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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Edit the Kubelet config file on every worker node**

           ```bash theme={null}
           sudo vi /var/lib/kubelet/config.yaml
           ```

           In the top-level YAML (same level as `kind:` / `apiVersion:`), add or set:

           ```yaml theme={null}
           protectKernelDefaults: true
           ```

        2. **(If also using kubelet flags) Edit the kubelet systemd drop-in on every worker node**

           ```bash theme={null}
           sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
           ```

           In the `KUBELET_SYSTEM_PODS_ARGS` (or the `Environment=`/`ExecStart=` line that holds kubelet flags), ensure this flag is present (or add it):

           ```text theme={null}
           --protect-kernel-defaults=true
           ```

        3. **Reload systemd and restart kubelet on every worker node**

           ```bash theme={null}
           sudo systemctl daemon-reload
           sudo systemctl restart kubelet.service
           ```

        4. **Verify kubelet is running with protect-kernel-defaults enabled on each worker node**

           ```bash theme={null}
           /bin/ps -fC kubelet | grep -- --protect-kernel-defaults
           ```

           Confirm that the output includes `--protect-kernel-defaults=true`.
      </Accordion>

      <Accordion title="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.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/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."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/admin/kubelet/](https://kubernetes.io/docs/admin/kubelet/)
