{"record":{"id":"83b54041006fec4f","repo":"netbirdio/netbird","slug":"invalid-signature","errorCode":null,"errorMessage":"invalid signature","messagePattern":"invalid signature","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/relay/auth/hmac/v2/validator.go","lineNumber":46,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshal token: %w\", err)\n\t}\n\n\tif len(token.Payload) < minLengthUnixTimestamp {\n\t\treturn errors.New(\"invalid payload: insufficient length\")\n\t}\n\n\thashFunc := token.AuthAlgo.New()\n\tif hashFunc == nil {\n\t\treturn fmt.Errorf(\"unsupported auth algorithm: %s\", token.AuthAlgo)\n\t}\n\n\th := hmac.New(hashFunc, v.secret)\n\th.Write(token.Payload)\n\texpectedMAC := h.Sum(nil)\n\n\tif !hmac.Equal(token.Signature, expectedMAC) {\n\t\treturn errors.New(\"invalid signature\")\n\t}\n\n\ttimestamp, err := strconv.ParseInt(string(token.Payload), 10, 64)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid payload: %w\", err)\n\t}\n\n\tif time.Now().Unix() > timestamp {\n\t\treturn fmt.Errorf(\"expired token\")\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":28,"sourceCodeEnd":60,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/shared/relay/auth/hmac/v2/validator.go#L28-L60","documentation":"The HMAC computed over the token payload with the validator's secret does not match the signature carried in the token (compared with hmac.Equal). Either the bytes were modified in transit, or — the usual cause — the validating relay holds a different HMAC secret than the issuer, so identical payloads produce different MACs.","triggerScenarios":"Relay configured with a different auth secret than management; a token minted in another environment (staging vs production) presented to this relay; payload bytes altered between issuer and validator.","commonSituations":"Self-hosted deployments where the shared secret env/config differs between the management and relay containers; a secret rotated on one side only; tokens cached across a rotation.","solutions":["Set the identical HMAC auth secret on management and the relay","After rotating the secret, restart both sides and discard previously issued tokens","Ensure the connection to the relay is TLS so no middlebox rewrites the frame"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := validator.Validate(data); err != nil {\n\tif err.Error() == \"invalid signature\" {\n\t\t// deny and alert: secret mismatch between issuer and validator is the usual cause\n\t}\n\treturn err\n}","preventionTips":["Distribute the same HMAC secret to management and relay via a shared secret store","Rotate secrets on both sides atomically and invalidate cached tokens","Serve relay connections over TLS so signatures cannot be corrupted in transit"],"tags":["relay","auth","hmac","secrets","configuration"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}