kubernetes/kops · warning
incorrect Audience
Error message
incorrect Audience
What it means
As a replay protection, VerifyToken requires the signed token's Audience field to equal gcetpm.AudienceNodeAuthentication. A token minted for a different audience (or with an empty audience) is rejected even if its signature is valid. This is a deliberate security check, not an infrastructure fault.
Source
Thrown at upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go:100
tokenBytes, err := base64.StdEncoding.DecodeString(authToken)
if err != nil {
return nil, fmt.Errorf("decoding authorization token: %w", err)
}
token := &gcetpm.AuthToken{}
if err = json.Unmarshal(tokenBytes, token); err != nil {
return nil, fmt.Errorf("unmarshalling authorization token: %w", err)
}
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")View on GitHub (pinned to 4c8573c808)
Solutions
- Ensure the node uses the standard gcetpm authenticator, which sets AudienceNodeAuthentication
- Check that signer and verifier link the same gcetpm package version (same constant value)
- Never mint tokens manually with a custom Audience for node authentication
- Verify no proxy rewrites or substitutes tokens between node and server
Defensive patterns
Strategy: validation
Validate before calling
tokenData := gcetpm.AuthTokenData{}
json.Unmarshal(token.Data, &tokenData)
if tokenData.Audience != gcetpm.AudienceNodeAuthentication {
return fmt.Errorf("token audience %q is not for node authentication", tokenData.Audience)
} Type guard
func isNodeAuthToken(td gcetpm.AuthTokenData) bool {
return td.Audience == gcetpm.AudienceNodeAuthentication
} Try / catch
token, err := verifier.VerifyToken(ctx, rawToken, request)
if err != nil {
if err.Error() == "incorrect Audience" {
return fmt.Errorf("token not intended for node authentication endpoint: %w", err)
}
return err
} Prevention
- Only use tokens minted by the standard gcetpm authenticator for node auth
- Use distinct verifier instances per audience/purpose; never share tokens across endpoints
- Keep the gcetpm audience constants identical on signer and verifier (same module version)
- Reject and log tokens with unexpected audiences for security auditing
When it happens
Trigger: VerifyToken receives a correctly signed and parsed token whose AuthTokenData.Audience differs from AudienceNodeAuthentication — e.g. a token generated for another purpose or by code setting a different audience constant.
Common situations: Token reuse across subsystems (e.g. using a verifier-audience token for node auth); custom client code hardcoding a wrong audience string; version skew where the audience constant value changed; replay of a captured token for a different endpoint.
Related errors
- could not determine ownership for instance %s
- failed to verify claim signature for node: %w
- failed to get GCE RSA attestation key from TPM: %w
- failed to marshal token data: %w
- failed to marshal token: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/3c3629a3807f6589.
Report an issue: GitHub.