{"record":{"id":"fd5289b7e87b2d6b","repo":"AlistGo/alist","slug":"sign-invalid","errorCode":null,"errorMessage":"sign invalid","messagePattern":"sign invalid","errorType":"http","errorClass":"ErrSignInvalid","httpStatus":401,"severity":"error","filePath":"pkg/sign/sign.go","lineNumber":12,"sourceCode":"package sign\n\nimport \"errors\"\n\ntype Sign interface {\n\tSign(data string, expire int64) string\n\tVerify(data, sign string) error\n}\n\nvar (\n\tErrSignExpired   = errors.New(\"sign expired\")\n\tErrSignInvalid   = errors.New(\"sign invalid\")\n\tErrExpireInvalid = errors.New(\"expire invalid\")\n\tErrExpireMissing = errors.New(\"expire missing\")\n)\n","sourceCodeStart":1,"sourceCodeEnd":16,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/pkg/sign/sign.go#L1-L16","documentation":"ErrSignInvalid from HMACSign.Verify: the expiry parsed fine and is not past, but recomputing HMAC-SHA256(secret, data+\":\"+expire) base64url does not match the supplied signature. Either the data, the secret, or the signature was altered.","triggerScenarios":"Calling Verify(data, sign) where the URL path (data) was modified after signing, the server's secret key changed (restarted with new JWT/sign secret), or the sign string was truncated/mangled.","commonSituations":"User edits the signed URL (changes path or filename); alist redeploys with a different token-sign secret so previously issued links all fail; proxy rewrites or decodes the path differently than at signing time.","solutions":["Use the signed URL exactly as issued — do not modify the path or query between signing and verification","Persist the signing secret (set it explicitly) so restarts do not invalidate outstanding links","Regenerate the sign for the new data via Sign(data, expire) if the data legitimately changed"],"exampleFix":"// before\nurl := signedURL\nurl.Path = \"/other/file.mp4\" // tampered -> ErrSignInvalid\n\n// after\n// request a new sign for the intended path\nsign := signer.Sign(\"/other/file.mp4\", time.Now().Add(time.Hour).Unix())","handlingStrategy":"validation","validationCode":"func hasValidShape(s string) bool {\n\tparts := strings.Split(s, \":\")\n\treturn len(parts) == 2 && parts[0] != \"\" && parts[1] != \"\"\n}","typeGuard":null,"tryCatchPattern":"err := signer.Verify(data, signStr)\nif errors.Is(err, sign.ErrSignInvalid) {\n\treturn fmt.Errorf(\"signature mismatch for %q: URL modified or secret changed\", data)\n}","preventionTips":["Keep the signed path byte-identical between signing and verification","Persist the signing secret so restarts do not invalidate links"],"tags":["signing","hmac","tampering","auth"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}