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

  1. Regenerate the token for the exact request body being sent; never reuse tokens across requests.
  2. Ensure the client hashes the identical byte slice that is sent as the body (same serialization, no gateway rewriting).
  3. Check that intermediaries (load balancers, service mesh, proxies) are not modifying the body.
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/fb58e91cd3d6977d. Report an issue: GitHub.