{"id":"GHSA-9r5x-wg6m-x2rc","summary":"Gitea: OAuth2 access token scope enforcement bypass via HTTP Basic authentication","details":"### Summary\n\nGitea fails to enforce OAuth2 access token scopes when the token is submitted via HTTP Basic authentication instead of a Bearer token. An OAuth2 application granted only `read:user` can use the same token as `Authorization: Basic base64(\u003ctoken\u003e:x-oauth-basic)` and perform write actions, including modifying profiles, adding email addresses, creating repositories, and deleting repositories as the authorizing user.\n\n### Details\n\n**Root cause:** `services/auth/basic.go` accepts OAuth2 access tokens through the Basic auth path but does not store the token scope in the request context:\n\n```go\n// services/auth/basic.go\nif uid != 0 {\n    store.GetData()[\"LoginMethod\"] = OAuth2TokenMethodName\n    store.GetData()[\"IsApiToken\"] = true   // scope is NOT set\n    return u, nil\n}\n```\n\nThe scope enforcement middleware in `routers/api/v1/api.go` exits early when `ApiTokenScope` is absent:\n\n```go\n// routers/api/v1/api.go — tokenRequiresScopes\nscope, scopeExists := ctx.Data[\"ApiTokenScope\"].(auth_model.AccessTokenScope)\nif ctx.Data[\"IsApiToken\"] != true || !scopeExists {\n    return   //\u003c- exits without checking scope, all actions permitted\n}\n```\n\nWhen a token arrives via Bearer, `ApiTokenScope` is populated and scope checks apply normally. When the same token arrives via Basic auth, `ApiTokenScope` is never set, so `tokenRequiresScopes` returns immediately and no scope is enforced.\n\n**Suggested fix:** When an OAuth2 access token is accepted in `services/auth/basic.go`, populate `ApiTokenScope` in the request context identically to the Bearer-token OAuth2 path.\n\n### PoC\n\n1. Create an OAuth2 application in Gitea.\n2. Authorize it as a normal user with scope `read:user` only.\n3. Take the resulting access token and call a write endpoint both ways:\n\n**Bearer | correctly blocked:**\n```\nAuthorization: Bearer \u003ctoken\u003e\nPATCH /api/v1/user/settings  -\u003e  403 Forbidden\n```\n\n**Basic | bypass:**\n```\nAuthorization: Basic base64(\u003ctoken\u003e:x-oauth-basic)\nPATCH /api/v1/user/settings  -\u003e  200 OK\n```\n\n**All verified bypass endpoints using a `read:user`-only token:**\n\n| Endpoint | Bearer | Basic |\n|---|---|---|\n| `PATCH /api/v1/user/settings` | 403 | 200 |\n| `POST /api/v1/user/emails` | 403 | 200 |\n| `POST /api/v1/user/repos` | 403 | 200 |\n| `PATCH /api/v1/repos/{owner}/{repo}` | 403 | 200 |\n| `DELETE /api/v1/repos/{owner}/{repo}` | 403 | 200 |\n\nThe bypass respects the user's normal repository permissions, it does not grant access to repositories the user cannot otherwise reach, and does not escalate to admin.\n\n### Impact\n\nAny OAuth2 application with any restricted scope can silently operate beyond its granted permissions by switching from Bearer to Basic auth. An attacker who obtains a token (e.g. via a malicious OAuth2 app a user authorized) can:\n\n- Modify the victim's profile and settings\n- Add attacker-controlled email addresses to the victim's account\n- Create repositories as the victim\n- Modify or delete the victim's private repositories\n\nThe entire OAuth2 scope system is effectively bypassed for any token submitted via Basic auth.","aliases":["CVE-2026-28699","GO-2026-5299"],"modified":"2026-06-25T19:56:28.101362846Z","published":"2026-06-16T23:40:34Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-06-16T23:40:34Z","nvd_published_at":null,"cwe_ids":["CWE-284","CWE-863"]},"references":[{"type":"WEB","url":"https://github.com/go-gitea/gitea/security/advisories/GHSA-9r5x-wg6m-x2rc"},{"type":"PACKAGE","url":"https://github.com/go-gitea/gitea"}],"affected":[{"package":{"name":"code.gitea.io/gitea","ecosystem":"Go","purl":"pkg:golang/code.gitea.io/gitea"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.26.2"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 1.26.1","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-9r5x-wg6m-x2rc/GHSA-9r5x-wg6m-x2rc.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N"}]}