kubernetes/kops · error
incorrect RequestHash
Error message
incorrect RequestHash
What it means
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.
Source
Thrown at upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go:110
tokenData := gcetpm.AuthTokenData{}
if err := json.Unmarshal(token.Data, &tokenData); err != nil {
return nil, fmt.Errorf("unmarshalling authorization token data: %w", err)
}
// Guard against replay attacks
if tokenData.Audience != gcetpm.AudienceNodeAuthentication {
return nil, fmt.Errorf("incorrect Audience")
}
timeSkew := math.Abs(time.Since(time.Unix(tokenData.Timestamp, 0)).Seconds())
if timeSkew > float64(v.opt.MaxTimeSkew) {
return nil, fmt.Errorf("incorrect Timestamp %v", tokenData.Timestamp)
}
// Verify the token has signed the body content.
requestHash := sha256.Sum256(body)
if !bytes.Equal(requestHash[:], tokenData.RequestHash) {
return nil, fmt.Errorf("incorrect RequestHash")
}
// Some basic validation to avoid requesting invalid instances.
if tokenData.GCPProjectID == "" {
return nil, fmt.Errorf("gcpProjectID is required")
}
if tokenData.Zone == "" {
return nil, fmt.Errorf("zone is required")
}
if tokenData.Instance == "" {
return nil, fmt.Errorf("instance is required")
}
// Verify node is in our cluster
if tokenData.GCPProjectID != v.opt.ProjectID {
return nil, fmt.Errorf("projectID does not match expected: got %q, want %q", tokenData.GCPProjectID, v.opt.ProjectID)
}
View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before: token minted for old body token := mint(bodyForRequestA) req.Body = bodyForRequestB // after newToken := mint(sha256.Sum256(bodyForRequestB)) req.Body = bodyForRequestB
Defensive patterns
Strategy: validation
Validate before calling
sum := sha256.Sum256(body)
if !bytes.Equal(sum[:], tokenData.RequestHash) {
return fmt.Errorf("body hash mismatch: token was minted for a different body")
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- incorrect Timestamp %v
- incorrect RequestHash
- error listing zones: %v
- failed to get GCE RSA attestation key from TPM: %w
- failed to sign token data: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/fb58e91cd3d6977d.
Report an issue: GitHub.