Skip to main content

Bootstrap Token Authentication Should Not Be Used For Users

More Info:

Bootstrap tokens are meant for node bootstrapping, not user authentication, and are weak for that purpose. Use OIDC instead.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Identify any configured bootstrap tokens

    • On every control plane node, list all bootstrap tokens:
      sudo kubeadm token list
    • If this returns one or more tokens, note their TOKEN, TTL, and USAGES fields.
  2. Determine whether tokens are used for user authentication

    • On any machine with kubectl access, list known cluster users/contexts and look for bootstrap tokens in kubeconfigs (they appear as token: <id>.<secret> in user entries):
      grep -RIn "token:" $HOME/.kube /etc/kubernetes/admin.conf /etc/kubernetes/*.conf 2>/dev/null
    • If any kubeconfig used by human users (e.g., developer/admin configs, CI systems) contains a bootstrap-style token ([a-z0-9]{6}\.[a-z0-9]{16}), record where it is used and by whom.
  3. Review RBAC bindings for bootstrap tokens

    • On any machine with kubectl access, check for ClusterRoleBindings/RoleBindings referencing bootstrap token groups (e.g. system:bootstrappers, system:node-bootstrapper):
      kubectl get clusterrolebindings -o yaml | grep -A5 "system:bootstrappers"
      kubectl get rolebindings -A -o yaml | grep -A5 "system:bootstrappers"
    • If these bindings are used to grant access to human users (e.g., tied to accounts that are not nodes), note the bindings for remediation.
  4. Decide and implement preferred user authentication (e.g. OIDC)

    • On every control plane node, inspect the API server manifest for OIDC configuration:
      sudo grep -E "oidc-" /etc/kubernetes/manifests/kube-apiserver.yaml
    • If OIDC (or another strong auth method) is not configured for user access, design and configure it according to your organization’s identity provider, then add the appropriate --oidc-* flags under the kube-apiserver container command: section in /etc/kubernetes/manifests/kube-apiserver.yaml. Saving this file will restart the API server.
  5. Remove or restrict bootstrap token use to node bootstrapping only

    • On any machine with kubectl access, remove any kubeconfigs used by humans that contain bootstrap tokens or replace them with OIDC / appropriate credentials.
    • On any control plane node, revoke unneeded tokens so they cannot be reused:
      # List to confirm
      sudo kubeadm token list
      # Revoke a specific token by ID (first field from list)
      sudo kubeadm token delete <token-id>
    • Adjust or delete any RBAC bindings from step 3 that grant non-node access through bootstrap token groups.
  6. Verify that bootstrap tokens are not used for user authentication

    • Confirm remaining tokens (if any) are limited to node bootstrapping, with tightly scoped RBAC and short TTLs:
      sudo kubeadm token list
    • On any machine with kubectl access, re-scan kubeconfigs for bootstrap-style tokens and ensure none are in use by human users:
      grep -RIn "token:" $HOME/.kube /etc/kubernetes/admin.conf /etc/kubernetes/*.conf 2>/dev/null
    • Verify users can authenticate via OIDC (or chosen mechanism) and that no operational workflows depend on bootstrap tokens.
Using kubectl

kubectl cannot remediate this finding because bootstrap token authentication is configured in the kube-apiserver static pod manifest on each control plane node at /etc/kubernetes/manifests/kube-apiserver.yaml. To address it, review and update that file directly on the control plane nodes as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
# Report possible misuse of bootstrap tokens as user credentials
# Run on: any machine with kubectl and cluster-admin access

set -euo pipefail

echo "=== 1) Detect all bootstrap tokens in the cluster ==="
# These are the credentials that *could* be misused by users
kubectl -n kube-system get secrets \
-o jsonpath='{range .items[?(@.type=="bootstrap.kubernetes.io/token")]}{.metadata.name}{"\t"}{.metadata.annotations.kubernetes\.io/description}{"\t"}{.metadata.annotations.kubernetes\.io/created-by}{"\n"}{end}' \
2>/dev/null | sort || echo "No bootstrap tokens found (or access denied)."

cat <<'EOF'

INTERPRETATION:
- Each line is: <secret-name> <description> <created-by>
- Investigate any token whose description or created-by suggests:
* An individual user account, team, or application
* Non-node / non-bootstrap use (e.g. "alice-cli", "devs", "jenkins-login")
- Bootstrap tokens should only be for node bootstrapping, not for user logins.

EOF

echo "=== 2) Inspect known bootstrap-token ClusterRoleBindings ==="
# Look for default or custom bindings that might grant user-like access
kubectl get clusterrolebindings.rbac.authorization.k8s.io -o json \
| jq -r '
.items[]
| select(
(.metadata.name | test("bootstrap"; "i")) or
([.subjects[]?.name] | join(",") | test("bootstrap-token"; "i"))
)
| [
.metadata.name,
(.roleRef.kind + "/" + .roleRef.name),
([.subjects[]? | (.kind + ":" + .name + "@" + (.namespace // ""))] | join(","))
]
| @tsv
' 2>/dev/null || echo "No obvious bootstrap-related ClusterRoleBindings found (or jq not installed)."

cat <<'EOF'

INTERPRETATION:
- Each line is: <binding-name> <roleRef-kind/name> <subjects>
- Review any binding that:
* Grants broad roles (e.g. cluster-admin, edit) to bootstrap-token subjects
* Appears to be used by users/apps rather than the kubelet bootstrap process

EOF

echo "=== 3) List valid authentication mechanisms on the API server(s) ==="
# Helps confirm whether OIDC (recommended alternative) is enabled
nodes=$(kubectl get nodes -l node-role.kubernetes.io/control-plane= -l node-role.kubernetes.io/master= -o name 2>/dev/null || true)
if [ -z "$nodes" ]; then
echo "Could not auto-detect control-plane nodes via labels. Inspect API server flags manually on each control-plane node."
else
echo "Control-plane nodes detected:"
echo "$nodes"
fi

cat <<'EOF'

MANUAL REVIEW NEEDED PER CONTROL-PLANE NODE (SSH REQUIRED):
- On EACH control-plane node, inspect the API server manifest:
sudo grep -E -- '--(enable-bootstrap-token-auth|oidc-issuer-url|oidc-client-id)' \
/etc/kubernetes/manifests/kube-apiserver.yaml

INTERPRETATION:
- If you see: --enable-bootstrap-token-auth=true
=> Bootstrap tokens are accepted by the API server. This is a risk if users
are given bootstrap tokens for login.
- If you see OIDC flags (e.g. --oidc-issuer-url, --oidc-client-id)
=> OIDC is configured, which is the recommended mechanism for user auth.
- This script CANNOT determine from the API server alone whether any *user*
is actually using bootstrap tokens; you must review:
* The bootstrap token secrets (step 1)
* The RBAC bindings to those tokens (step 2)
* Your external access patterns and documentation

A PROBLEM IS INDICATED WHEN:
- Bootstrap tokens exist whose description/usage clearly points to human users
or non-node workloads; AND/OR
- RBAC bindings give bootstrap-token subjects user-like or broad cluster access;
AND
- The API server has --enable-bootstrap-token-auth=true.

In such cases, plan to:
- Migrate those users/apps to OIDC-based authentication, and then
- Remove or rotate the offending bootstrap tokens and adjust RBAC bindings, and/or
- Disable bootstrap token auth if not required for node bootstrapping.

EOF