{"record":{"id":"139057b9017e5409","repo":"henrygd/beszel","slug":"unsupported-release-digest-algorithm-q","errorCode":null,"errorMessage":"unsupported release digest algorithm %q","messagePattern":"unsupported release digest algorithm %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/ghupdate/checksum.go","lineNumber":19,"sourceCode":"package ghupdate\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc verifyAssetChecksum(path, digest string) error {\n\talgorithm, expectedHex, ok := strings.Cut(digest, \":\")\n\tif !ok || algorithm == \"\" || expectedHex == \"\" {\n\t\treturn fmt.Errorf(\"invalid release digest %q\", digest)\n\t}\n\tif !strings.EqualFold(algorithm, \"sha256\") {\n\t\treturn fmt.Errorf(\"unsupported release digest algorithm %q\", algorithm)\n\t}\n\n\texpected, err := hex.DecodeString(expectedHex)\n\tif err != nil || len(expected) != sha256.Size {\n\t\treturn fmt.Errorf(\"invalid SHA-256 release digest %q\", digest)\n\t}\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open release for checksum verification: %w\", err)\n\t}\n\tdefer file.Close()\n\n\thash := sha256.New()\n\tif _, err := io.Copy(hash, file); err != nil {\n\t\treturn fmt.Errorf(\"failed to calculate release checksum: %w\", err)\n\t}\n\tactual := hash.Sum(nil)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/ghupdate/checksum.go#L1-L37","documentation":"After splitting the digest on \":\", the library only supports the sha256 algorithm (compared case-insensitively). If the digest prefix names any other algorithm — md5, sha1, sha512, etc. — verification is refused because the code only knows how to compute and compare SHA-256. This guards against silently accepting a weaker or unknown hash scheme.","triggerScenarios":"ghupdate.Update -> update -> verifyAssetChecksum with a release asset digest like \"md5:...\", \"sha512:...\", or \"sha1:...\" published on the release, typically from a manually uploaded asset or a mirror that recomputed digests with a different algorithm.","commonSituations":"Self-hosted release pipelines that publish md5 or sha512 checksum files; third-party forks of beszel publishing their own digest format; older release tooling predating GitHub's sha256 digest support.","solutions":["Re-publish the release asset so it carries a sha256 digest (GitHub does this automatically for release assets).","If you control the mirror, convert the published digest to \"sha256:<hex>\" format.","Fork/patch verifyAssetChecksum to support the algorithm you use, but prefer upgrading to sha256."],"exampleFix":"// before\ndigest := \"sha512:9d4e...\"\n// after\ndigest := \"sha256:3f2a...\" // only sha256 is accepted","handlingStrategy":"validation","validationCode":"algo := strings.SplitN(asset.Digest, \":\", 2)[0]\nif !strings.EqualFold(algo, \"sha256\") {\n    return fmt.Errorf(\"unsupported digest algorithm %q; republish asset with sha256\", algo)\n}","typeGuard":null,"tryCatchPattern":"updated, err := ghupdate.Update(cfg)\nif err != nil && strings.Contains(err.Error(), \"unsupported release digest algorithm\") {\n    log.Printf(\"release uses an unsupported hash algorithm (%v); pin to a sha256 release\", err)\n}","preventionTips":["Standardize release pipelines on sha256 digests.","Audit fork/mirror release assets for their hash algorithm.","Never hand-generate digests with md5sum/sha1sum."],"tags":["checksum","algorithm","sha256","self-update"],"backgroundTag":"unsupported-hash-algorithm","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}