🛡️ CVE-2026-50105 — gitea.dev
Description
Gitea: RSS/Atom feed handlers bypass API-token scope & public-only confinement (incomplete fix of #37698)
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 route differs:
- Token A: scopes
["public-only", "read:repository"] - Token B: scopes
["read:issue"]
```bash
# Token A — download is correctly blocked, feeds leak private content:
curl -u alice:$TOKEN_A https://<host>/alice/secret/raw/branch/main/secret.txt # => 403 (fix works)
curl -u alice:$TOKEN_A https://<host>/alice/secret/rss/branch/main # => 200, <title>SECRET-COMMIT-MARKER ...</title>
curl -u alice:$TOKEN_A https://<host>/alice/secret/releases.rss # => 200, SECRET-RELEASE-MARKER ...
curl -u alice:$TOKEN_A "https://<host>/alice.rss" # => 200, private activity
# Token B — wrong scope category, same split:
curl -u alice:$TOKEN_B https://<host>/alice/secret/raw/branch/main/secret.txt # => 403
curl -u alice:$TOKEN_B https://<host>/alice/secret/rss/branch/main # => 200, private commit leaked
```
Anonymous
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality low, integrity none, availability none.
Weakness class
CVE-2026-50105 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.
Affected software
CVE-2026-50105 is recorded against 2 packages.
- code.gitea.io/gitea
- gitea.dev
Timeline and source
Published on 21 July 2026 and last revised on 22 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.
References
Details
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| code.gitea.io/gitea | — | — |
| gitea.dev | — | — |
References
Similar Threats
- High CVE-2021-3382
- High CVE-2020-14144
- Medium CVE-2022-38183
- Medium CVE-2022-1928
- Unknown CVE-2019-1010261
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
Free Vulnerability Check
Is your site affected by CVE-2026-50105?
BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-50105 and other known CVE records.
Scan My Site Free →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.