{"record":{"id":"fb58e91cd3d6977d","repo":"kubernetes/kops","slug":"incorrect-requesthash-fb58e9","errorCode":null,"errorMessage":"incorrect RequestHash","messagePattern":"incorrect RequestHash","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go","lineNumber":110,"sourceCode":"\n\ttokenData := gcetpm.AuthTokenData{}\n\tif err := json.Unmarshal(token.Data, &tokenData); err != nil {\n\t\treturn nil, fmt.Errorf(\"unmarshalling authorization token data: %w\", err)\n\t}\n\n\t// Guard against replay attacks\n\tif tokenData.Audience != gcetpm.AudienceNodeAuthentication {\n\t\treturn nil, fmt.Errorf(\"incorrect Audience\")\n\t}\n\ttimeSkew := math.Abs(time.Since(time.Unix(tokenData.Timestamp, 0)).Seconds())\n\tif timeSkew > float64(v.opt.MaxTimeSkew) {\n\t\treturn nil, fmt.Errorf(\"incorrect Timestamp %v\", tokenData.Timestamp)\n\t}\n\n\t// Verify the token has signed the body content.\n\trequestHash := sha256.Sum256(body)\n\tif !bytes.Equal(requestHash[:], tokenData.RequestHash) {\n\t\treturn nil, fmt.Errorf(\"incorrect RequestHash\")\n\t}\n\n\t// Some basic validation to avoid requesting invalid instances.\n\tif tokenData.GCPProjectID == \"\" {\n\t\treturn nil, fmt.Errorf(\"gcpProjectID is required\")\n\t}\n\tif tokenData.Zone == \"\" {\n\t\treturn nil, fmt.Errorf(\"zone is required\")\n\t}\n\tif tokenData.Instance == \"\" {\n\t\treturn nil, fmt.Errorf(\"instance is required\")\n\t}\n\n\t// Verify node is in our cluster\n\tif tokenData.GCPProjectID != v.opt.ProjectID {\n\t\treturn nil, fmt.Errorf(\"projectID does not match expected: got %q, want %q\", tokenData.GCPProjectID, v.opt.ProjectID)\n\t}\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go#L92-L128","documentation":"VerifyToken compares the SHA-256 hash of the HTTP request body against tokenData.RequestHash carried in the signed token. A mismatch means the token was not signed over the exact body being presented, so the request content may have been tampered with or the token reused against a different payload.","triggerScenarios":"The client sends a token whose signed RequestHash does not equal sha256(body) of the incoming request — e.g. the body was modified after token generation, the token from one request is replayed on another request with a different body, or the client hashed a different serialization of the payload.","commonSituations":"Proxies or middleware rewriting/re-encoding the request body in transit, clients reusing a previously obtained token for a new request, byte-level differences from JSON re-serialization (field order, whitespace), or a buggy client hashing the wrong bytes.","solutions":["Regenerate the token for the exact request body being sent; never reuse tokens across requests.","Ensure the client hashes the identical byte slice that is sent as the body (same serialization, no gateway rewriting).","Check that intermediaries (load balancers, service mesh, proxies) are not modifying the body.","Compare the hashing algorithm/encoding used client-side with the verifier's sha256 of the raw body."],"exampleFix":"// before: token minted for old body\ntoken := mint(bodyForRequestA)\nreq.Body = bodyForRequestB\n// after\nnewToken := mint(sha256.Sum256(bodyForRequestB))\nreq.Body = bodyForRequestB","handlingStrategy":"validation","validationCode":"sum := sha256.Sum256(body)\nif !bytes.Equal(sum[:], tokenData.RequestHash) {\n\treturn fmt.Errorf(\"body hash mismatch: token was minted for a different body\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mint the token over the exact serialized bytes sent as the body","Never reuse tokens across different requests","Avoid proxies/middleware that rewrite request bodies","Unit-test client hashing against the verifier's expected hash"],"tags":["gcp","tpm","authentication","integrity"],"backgroundTag":"request-signature-mismatch","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"}