crowdsecurity/crowdsec · warning

failed to cast machineID to string

Error message

failed to cast machineID to string

What it means

The MachineID claim exists but is not a JSON string, so the assertion rawID.(string) fails and getMachineIDFromContext returns "failed to cast machineID to string". The comment notes this should never happen — it guards against a token whose machine-ID claim is a number, object, or other non-string type.

Source

Thrown at pkg/apiserver/controllers/v1/utils.go:52

	return false
}

func getMachineIDFromContext(ctx *gin.Context) (string, error) {
	claims := jwt.ExtractClaims(ctx)
	if claims == nil {
		return "", errors.New("failed to extract claims")
	}

	rawID, ok := claims[middlewares.MachineIDKey]
	if !ok {
		return "", errors.New("MachineID not found in claims")
	}

	id, ok := rawID.(string)
	if !ok {
		// should never happen
		return "", errors.New("failed to cast machineID to string")
	}

	return id, nil
}

func (*Controller) AbortRemoteIf(option bool) gin.HandlerFunc {
	return func(gctx *gin.Context) {
		if !option {
			return
		}

		if isUnixSocket(gctx) {
			return
		}

		incomingIP := gctx.ClientIP()
		if incomingIP != "127.0.0.1" && incomingIP != "::1" {
			gctx.JSON(http.StatusForbidden, gin.H{"message": "access forbidden"})

View on GitHub (pinned to 909b515798)

Solutions

  1. Re-authenticate the machine to obtain a token with a string machine-ID claim
  2. Fix custom issuing code to store the machine ID as a string: fmt.Sprintf or the original string value
  3. If you control the claim source, convert numbers with strconv before signing

Example fix

// before
claims[middlewares.MachineIDKey] = machineIntID
// after
claims[middlewares.MachineIDKey] = fmt.Sprintf("%d", machineIntID)
Defensive patterns

Strategy: type-guard

Validate before calling

raw, ok := claims[middlewares.MachineIDKey]
if !ok { return errors.New("missing machineID") }
if _, ok := raw.(string); !ok {
    return fmt.Errorf("machineID claim must be a string, got %T", raw)
}

Type guard

s, ok := rawID.(string)
if !ok { /* token minted with a non-string machine ID; reject */ }

Try / catch

machineID, err := getMachineIDFromContext(c)
if err != nil {
    c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "malformed token"})
    return
}

Prevention

When it happens

Trigger: A JWT whose machine ID claim was signed as a non-string JSON value (e.g. numeric ID or nested object), produced by custom or third-party token-issuing code rather than crowdsec's normal login flow.

Common situations: Hand-rolled token generators serializing the machine ID as a number; corrupted or manipulated tokens; test fixtures with claims built as map[string]interface{}{...: 42}.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/6f398056a0439cba. Report an issue: GitHub.