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

  1. Ensure the node uses the standard gcetpm authenticator, which sets AudienceNodeAuthentication
  2. Check that signer and verifier link the same gcetpm package version (same constant value)
  3. Never mint tokens manually with a custom Audience for node authentication
  4. 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

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


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