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
Remediation
Manual Steps
-
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, andUSAGESfields.
- On every control plane node, list all bootstrap tokens:
-
Determine whether tokens are used for user authentication
- On any machine with
kubectlaccess, list known cluster users/contexts and look for bootstrap tokens in kubeconfigs (they appear astoken: <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.
- On any machine with
-
Review RBAC bindings for bootstrap tokens
- On any machine with
kubectlaccess, 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.
- On any machine with
-
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 thekube-apiservercontainercommand:section in/etc/kubernetes/manifests/kube-apiserver.yaml. Saving this file will restart the API server.
- On every control plane node, inspect the API server manifest for OIDC configuration:
-
Remove or restrict bootstrap token use to node bootstrapping only
- On any machine with
kubectlaccess, 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 confirmsudo 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.
- On any machine with
-
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
kubectlaccess, 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.
- Confirm remaining tokens (if any) are limited to node bootstrapping, with tightly scoped RBAC and short TTLs:
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