{"record":{"id":"4ee2c9f9a7e7381a","repo":"cloudflare/cloudflared","slug":"aud-array-contains-non-string-elements","errorCode":null,"errorMessage":"aud array contains non-string elements","messagePattern":"aud array contains non-string elements","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":91,"sourceCode":"func (p *jwtPayload) UnmarshalJSON(data []byte) error {\n\ttype Alias jwtPayload\n\tif err := json.Unmarshal(data, (*Alias)(p)); err != nil {\n\t\treturn err\n\t}\n\tvar audParser struct {\n\t\tAud any `json:\"aud\"`\n\t}\n\tif err := json.Unmarshal(data, &audParser); err != nil {\n\t\treturn err\n\t}\n\tswitch aud := audParser.Aud.(type) {\n\tcase string:\n\t\tp.Aud = []string{aud}\n\tcase []any:\n\t\tfor _, a := range aud {\n\t\t\ts, ok := a.(string)\n\t\t\tif !ok {\n\t\t\t\treturn errors.New(\"aud array contains non-string elements\")\n\t\t\t}\n\t\t\tp.Aud = append(p.Aud, s)\n\t\t}\n\tdefault:\n\t\treturn errors.New(\"aud field is not a string or an array of strings\")\n\t}\n\treturn nil\n}\n\nfunc (p jwtPayload) isExpired() bool {\n\treturn int(time.Now().Unix()) > p.Exp\n}\n\nconst (\n\tlockRetryInterval  = 2 * time.Second\n\tlockTimeout        = 10 * time.Minute\n\tstartTimeTolerance = int64(1000) // milliseconds\n)","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L73-L109","documentation":"jwtPayload.UnmarshalJSON accepts an \"aud\" claim that is either a single string or an array of strings. If the aud value is a JSON array containing any non-string element, unmarshalling fails with this error so malformed tokens are rejected at parse time instead of producing a corrupted Audience field.","triggerScenarios":"Unmarshalling a JWT payload (or the metadata JWT header/payload) where aud is an array containing numbers, nulls, booleans, or nested objects, e.g. \"aud\": [\"app\", 123] or [null].","commonSituations":"Token issuers that serialize client IDs as numbers instead of strings, hand-crafted or third-party tokens with heterogeneous aud arrays, or misconfigured identity providers emitting numeric account IDs in the audience claim.","solutions":["Fix the token issuer to emit all aud elements as JSON strings (quote numeric IDs).","Inspect the offending token's payload (decode base64 JSON) to find the non-string element and correct it at the source.","If you cannot fix the issuer, pre-validate or rewrite the token payload before passing it to this library."],"exampleFix":"// before (issuer side): \"aud\": [12345]\n// after (issuer side): \"aud\": [\"12345\"]","handlingStrategy":"validation","validationCode":"audVal, ok := payloadMap[\"aud\"].([]any)\nif ok {\n    for _, a := range audVal {\n        if _, isStr := a.(string); !isStr {\n            return fmt.Errorf(\"aud array contains non-string element: %v\", a)\n        }\n    }\n}","typeGuard":"func isStringArray(v any) bool {\n    arr, ok := v.([]any)\n    if !ok {\n        return false\n    }\n    for _, a := range arr {\n        if _, isStr := a.(string); !isStr {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"p := jwtPayload{}\nif err := json.Unmarshal(rawPayload, &p); err != nil {\n    return fmt.Errorf(\"malformed JWT payload (check aud claim types): %w\", err)\n}","preventionTips":["Ensure token issuers serialize all audience values as JSON strings (quote numeric IDs).","Decode and inspect token payloads with a JWT debugger before deploying new issuers.","Add issuer-side contract tests asserting aud is string or []string."],"tags":["jwt","validation","audience-claim","token"],"backgroundTag":"schema-validation-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}