A AegiFlow
MEDIUMCVSS 4.3

CVE-2026-50105

Gitea: RSS/Atom feed handlers bypass API-token scope & public-only confinement (incomplete fix of #37698)

Published
2026-07-21
Modified
2026-07-21
Aliases
GHSA-6cqf-375w-639g
Sources
github-advisory

Summary

### Summary Gitea's RSS/Atom feed handlers accept API-token Basic auth but perform **no token-scope or public-only enforcement**. A personal access token that is correctly blocked (HTTP 403) from a private repository on `/raw`, `/media`, `/archive`, and `/releases/download/...` — because it is marked *public-only* or lacks the `repository` scope category — still returns that repository's private content through the feed routes. This is a token-confinement bypass and appears to be an incomplete fix of #37698, which added that scope enforcement to the download handlers but not to the sibling feed handlers. This is **not** a cross-user access bug: the requesting account must still legitimately have repo read access (`RepoAssignment` + `reqUnitCodeReader` are enforced). What is bypassed is the guarantee that a *confined* token cannot reach private content — which is exactly the property #37698 was shipped to provide for downloads, and which matters when such a token is handed to a third-party service/CI, leaked, or used in a lower-trust integration. ### Details #37698 added `context.CheckTokenScopes` / `CheckRepoScopedToken` (`services/context/permission.go`) to the raw / media / archive / attachment download handlers, so a public-only or wrong-scope-category token cannot read private-repo content even when the owning user otherwise has access. The feed handlers are registered with `webAuth.AllowBasic` (so they accept token Basic auth) but call no scope / public-only check. A grep for `CheckTokenScopes` / `CheckRepoScopedToken` / `IsApiToken` across `routers/web/feed/` and the release feed handlers returns nothing. Affected routes (all token-reachable via `webAuth.AllowBasic`, none call the scope check): | Route | Handler | Private data exposed | |---|---|---| | `GET /{owner}/{repo}.rss` / `.atom` | `repo.Home` → `handleRepoHomeFeed` (`view_home.go`) | last-10 commits: SHA, full message, author name + email | | `GET /{owner}/{repo}/rss/branch/*`, `/atom/branch/*` | `feed.RenderBranchFeed*` → `ShowBranchFeed` (`routers/web/feed/branch.go`) | same commit data, any branch | | `GET /{owner}/{repo}/releases.rss` / `.atom` | `ReleasesFeedRSS/Atom` (`routers/web/repo/release.go`) → `ShowReleaseFeed` | private release names, notes, descriptions | | `GET /{owner}/{repo}/tags.rss` / `.atom` | `TagsListFeedRSS/Atom` → `ShowReleaseFeed` | private tag names + messages | | `GET /{user}.rss` / `.atom` | `showUserFeed` (`routers/web/feed/profile.go`), `includePrivate = self \|\| admin` | the token owner's private cross-repo activity stream | Inconsistency that pins this down: the branch-feed routes sit in the **same route group** as `/raw`, `/media`, `/archive` (all of which call `checkDownloadTokenScope`), and `releases.rss` sits next to `/releases/attachments/{uuid}` and `/releases/download/...` (both go through `ServeAttachment` → scope check). Only the feeds were missed. The API equivalents (`ListReleases` / `ListTags`) are scope-gated via `tokenRequiresScopes`. Two distinct confinement bypasses: 1. **Public-only bypass.** A token created with the *public-only* option is blocked (403) from a private repo on `/raw`, `/archive`, `/releases/download/...`, but returns private commit / release data via `.../releases.rss`, `.../rss/branch/*`, `/{owner}/{repo}.rss`, and the owner's private activity via `/{user}.rss`. 2. **Scope-category bypass.** A token scoped to only e.g. `read:issue` (no `read:repository`) is rejected by the download handlers but reads repository commit/release content via the feeds. ### PoC Verified live against the official `gitea/gitea:1.26.2` Docker image (sqlite, feeds enabled). Setup: non-admin user `alice`; private repo `alice/secret` with a commit `"SECRET-COMMIT-MARKER ..."` (file `secret.txt`) and a release `"Private Release"` / body `"SECRET-RELEASE-MARKER ..."`. Two confined personal access tokens, both sent via HTTP Basic so the auth method is identical across download and feed — only the rou

Affected packages

EcosystemPackageAffected versionsFixed versions
Gocode.gitea.io/gitea1.27.0

Remediation: Upgrade to 1.27.0 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.

CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.