{"record":{"id":"66f72438d7660551","repo":"kubernetes/kops","slug":"failed-to-verify-claim-signature-for-node-w","errorCode":null,"errorMessage":"failed to verify claim signature for node: %w","messagePattern":"failed to verify claim signature for node: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go","lineNumber":188,"sourceCode":"\t\t}\n\t\tcapiMachine = m\n\t}\n\n\t// Check if this is a CAPG managed instance\n\tif instanceGroupName == \"\" && capiMachine == nil {\n\t\treturn nil, fmt.Errorf(\"could not determine ownership for instance %s\", instance.SelfLink)\n\t}\n\n\t// Verify the token has a valid GCE TPM signature.\n\t{\n\t\t// Note - we might be able to avoid this call by including the attestation certificate (signed by GCE) in the claim.\n\t\ttpmSigningKey, err := v.getTPMSigningKey(ctx, &tokenData)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif !verifySignature(tpmSigningKey, token.Data, token.Signature) {\n\t\t\treturn nil, fmt.Errorf(\"failed to verify claim signature for node: %w\", err)\n\t\t}\n\t}\n\n\tsans, err := GetInstanceCertificateAlternateNames(instance)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tchallengeEndpoint := instance.NetworkInterfaces[0].NetworkIP + \":\" + strconv.Itoa(wellknownports.NodeupChallenge)\n\n\tresult := &bootstrap.VerifyResult{\n\t\tNodeName:          instance.Name,\n\t\tInstanceGroupName: instanceGroupName,\n\t\tCAPIMachine:       capiMachine,\n\t\tCertificateNames:  sans,\n\t\tChallengeEndpoint: challengeEndpoint,\n\t}\n","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go#L170-L206","documentation":"The TPM claim signature over the token data did not verify against the instance's GCE Shielded VM signing key. Note the code wraps err which is nil at that point, so the message carries no underlying cause — the RSA-PKCS verification simply returned false.","triggerScenarios":"verifySignature(tpmSigningKey, token.Data, token.Signature) returns false: the token's signature doesn't match token.Data when checked against the key fetched from GetShieldedInstanceIdentity.","commonSituations":"Tampered or forged token (potential attack — investigate); node software and verifier using mismatched token formats/versions; signing key rotated by GCE between token creation and verification; corrupted request body altering signed content.","solutions":["Investigate the source node for tampering or a compromised token — treat as a security signal if unexpected","Recreate/replace the node so it generates a fresh TPM-signed token","Align the node-side gcetpm token producer version with the verifier","Check for proxy/middleware modifying the request body between signing and verification"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// confirm the token is well-formed and unmodified before sending\nif sha256.Sum256(body) != tokenData.RequestHash {\n    return errors.New(\"request body does not match signed hash — body was modified\")\n}","typeGuard":null,"tryCatchPattern":"result, err := verifier.VerifyToken(ctx, req, authToken, body)\nif err != nil && strings.Contains(err.Error(), \"failed to verify claim signature\") {\n    log.SecurityEvent(\"TPM signature mismatch for node\", err) // investigate node for tampering\n    return nil, err // never retry-sign; treat as untrusted\n}","preventionTips":["Never modify the request body between client signing and server verification (no mutating proxies)","Keep node-side token producer and verifier versions in lockstep","Monitor for repeated signature failures — they indicate tampering or compromised nodes","Ensure node clock/config is sane so fresh, correctly signed tokens are produced"],"tags":["gce","tpm","signature","security","attestation"],"backgroundTag":"signature-verification-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}