This release fixes a security issue reported by @xmsama.
Security
Git LFS write checks bypassed by a caller-supplied service parameter (GHSA-g3x7-3892-v6r2, high)
Soft Serve authorizes every HTTP Git and Git LFS request in one middleware,
which picks the permission checks to apply from the Git service being
requested. LFS routes carry no service in their path, so the value fell back
to a service query parameter supplied by the caller, and that branch was
evaluated before the one matching the LFS path.
Appending ?service=git-upload-pack to an LFS upload or lock request
therefore skipped the write-access requirement entirely. Under the shipped
defaults, where anonymous access is read-only and LFS is enabled, no
credentials were needed at all against a public repository; on any other
server, read access was enough.
The consequence is object substitution. The upload endpoint does not verify
that the content it receives hashes to the object ID in the URL, so content
can be stored under an ID belonging to a legitimate file, and anyone who
later runs git lfs pull receives it. Two lesser effects follow from the
same bypass: a read-only user could take LFS locks on arbitrary paths, and
because the lfs.enabled check lived in the skipped branch, a server with
LFS turned off still had reachable, writable LFS endpoints.
LFS requests are now authorized by their route rather than by the service
they claim, and the upload and lock-create handlers check write access
themselves so that a future routing mistake cannot become an unauthenticated
write. Repository contents were never exposed by this: read access was still
required to reach the repository at all.
Anyone who ran an affected version with LFS enabled should treat their LFS
object store as untrusted and re-verify objects against their expected
hashes. Affected versions are v0.6.0 through v0.12.0.
Changelog
Fixed
- 27f5245: fix: authorize LFS requests by route rather than claimed service (@taciturnaxolotl)
Other stuff
- 66cf80e: v0.12.1 (@taciturnaxolotl)
Verifying the artifacts
First, download the checksums.txt file and the checksums.txt.sigstore.json file files, for example, with wget:
wget 'https://github.com/charmbracelet/soft-serve/releases/download/v0.12.1/checksums.txt'
wget 'https://github.com/charmbracelet/soft-serve/releases/download/v0.12.1/checksums.txt.sigstore.json'Then, verify it using cosign:
cosign verify-blob \
--certificate-identity 'https://github.com/charmbracelet/meta/.github/workflows/goreleaser.yml@refs/heads/main' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
--bundle 'checksums.txt.sigstore.json' \
./checksums.txtIf the output is Verified OK, you can safely use it to verify the checksums of other artifacts you downloaded from the release using sha256sum:
sha256sum --ignore-missing -c checksums.txtDone! You artifacts are now verified!
Thoughts? Questions? We love hearing from you. Feel free to reach out on X, Discord, Slack, The Fediverse, Bluesky.
