{"record":{"id":"db4a7febc7eb4fd0","repo":"k3s-io/k3s","slug":"header-node-name-does-not-match-auth-node-name","errorCode":null,"errorMessage":"header node name does not match auth node name","messagePattern":"header node name does not match auth node name","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/nodepassword/validate.go","lineNumber":58,"sourceCode":"// Node password authentication is used when requesting kubelet certificates, and verifies that the\n// credentials are valid for the requested node name, and that the node password is valid if it exists.\n// These checks prevent a user with access to one agent from requesting kubelet certificates that\n// could be used to impersonate another cluster member.\nfunc GetNodeAuthValidator(ctx context.Context, control *config.Control) NodeAuthValidator {\n\tdeferredNodes := map[string]bool{}\n\tvar mu sync.Mutex\n\n\treturn func(req *http.Request) (string, int, error) {\n\t\tnode, err := getNodeInfo(req)\n\t\tif err != nil {\n\t\t\treturn \"\", http.StatusBadRequest, err\n\t\t}\n\n\t\t// node identity auth uses an existing kubelet client cert instead of auth token.\n\t\t// If used, validate that the node identity matches the requested node name.\n\t\tnodeName, isNodeAuth := identifier.NodeIdentity(node.User)\n\t\tif isNodeAuth && nodeName != node.Name {\n\t\t\treturn \"\", http.StatusBadRequest, errors.New(\"header node name does not match auth node name\")\n\t\t}\n\n\t\tif controller == nil {\n\t\t\tif node.Name == os.Getenv(\"NODE_NAME\") {\n\t\t\t\t// If we're verifying our own password, verify it locally and ensure a secret later.\n\t\t\t\treturn verifyLocalPassword(ctx, control, &mu, deferredNodes, node)\n\t\t\t} else if control.DisableAPIServer && !isNodeAuth {\n\t\t\t\t// If we're running on an etcd-only node, and the request didn't use Node Identity auth,\n\t\t\t\t// defer node password verification until an apiserver joins the cluster.\n\t\t\t\treturn verifyRemotePassword(ctx, control, &mu, deferredNodes, node)\n\t\t\t}\n\t\t\t// Otherwise, reject the request until the controller is ready.\n\t\t\treturn \"\", http.StatusServiceUnavailable, util.ErrCoreNotReady\n\t\t}\n\n\t\t// verify that the node exists, if using Node Identity auth\n\t\tif err := controller.verifyNode(ctx, node); err != nil {\n\t\t\treturn \"\", http.StatusUnauthorized, err","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/nodepassword/validate.go#L40-L76","documentation":"Node-password authentication accepts either a shared token or kubelet client-cert node identity (system:node:<name>). When request authentication resolved the caller as a node identity and that identity's node name differs from the node name header sent with the request, the request is rejected with HTTP 400 as a probable spoof or misconfiguration.","triggerScenarios":"A kubelet credential minted for node A authenticates a request whose <program>-Node-Name header says node B; typically one node reusing another node's client cert or client-cert/data-dir copied between machines.","commonSituations":"Cloning VMs/images including /var/lib/rancher/k3s; a node renamed after join; an attempt to proxy requests for other nodes using a single node's identity.","solutions":["On the affected node, remove the duplicated credentials/identity state (e.g. wipe /var/lib/rancher/k3s and rejoin) so it gets its own client cert.","Ensure the node name (hostname / --node-name) matches the name in the client cert CN system:node:<name> and the header value.","Never copy node data directories between hosts; treat node certs as node-specific."],"exampleFix":"# before: cloned node keeps node-a's certs but registers as node-b\n# after: wipe and rejoin with its own identity\nrm -rf /var/lib/rancher/k3s/agent\nk3s agent --server https://10.0.0.10:6443 --token ...","handlingStrategy":"validation","validationCode":"if nodeName, ok := identifier.NodeIdentity(user); ok && nodeName != strings.ToLower(reqNodeName) {\n    return http.StatusBadRequest, fmt.Errorf(\"node identity %q != header %q\", nodeName, reqNodeName)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never clone node data directories; node certs identify the node.","Rejoin (wipe agent state) after renaming a node so cert CN and hostname agree."],"tags":["authentication","security","tls","node"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}