CVE-2026-50105

CVE-2026-50105 is a medium-severity missing authorization vulnerability in code.gitea.io/gitea (go), affecting versions < 1.27.0. It is fixed in 1.27.0.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

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

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.HomehandleRepoHomeFeed (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/AtomShowReleaseFeed 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"]
# 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 baseline returns 404 on the repo feeds (data is genuinely private) and a marker-free 200 on
/alice.rss (public activity only), confirming the leak is gated only by the missing token check.

Suggested remediation

Add a token-scope check at the top of each feed handler, mirroring checkDownloadTokenScope:

if context.CheckRepoScopedToken(ctx, ctx.Repo.Repository, auth_model.Read); ctx.Written() {
    return
}

for ShowBranchFeed, ShowRepoFeed, ShowFileFeed, ShowReleaseFeed (repo feeds). For the user
feed, gate includePrivate behind a non-public-only token (or require the user / repository
scope) so a confined token can't pull private activity.

Impact

Information disclosure of private commit metadata (SHA, message, author name+email),
release/tag notes, and the owner's private activity stream, to the holder of a confined token
that was specifically configured not to reach private content. Not raw file blobs (feeds don't
serve file contents). Requires a token belonging to an account that already has repo read access, so
the realistic threat is a leaked / shared / lower-trust token rather than an anonymous attacker ,
which is precisely the threat model #37698 addressed for downloads.

The application does not perform an authorization check before performing a sensitive operation. Typical impact: unauthorized access to restricted functionality or data.

CVE-2026-50105 has a CVSS score of 4.3 (Medium). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.27.0); upgrading removes the vulnerable code path.

Affected versions

code.gitea.io/gitea (< 1.27.0)

Security releases

code.gitea.io/gitea → 1.27.0 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade code.gitea.io/gitea to 1.27.0 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-50105? CVE-2026-50105 is a medium-severity missing authorization vulnerability in code.gitea.io/gitea (go), affecting versions < 1.27.0. It is fixed in 1.27.0. The application does not perform an authorization check before performing a sensitive operation.
  2. How severe is CVE-2026-50105? CVE-2026-50105 has a CVSS score of 4.3 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of code.gitea.io/gitea are affected by CVE-2026-50105? code.gitea.io/gitea (go) versions < 1.27.0 is affected.
  4. Is there a fix for CVE-2026-50105? Yes. CVE-2026-50105 is fixed in 1.27.0. Upgrade to this version or later.
  5. Is CVE-2026-50105 exploitable, and should I be worried? Whether CVE-2026-50105 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-50105 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-50105? Upgrade code.gitea.io/gitea to 1.27.0 or later.

Other vulnerabilities in code.gitea.io/gitea

Stop the waste.
Protect your environment with Kodem.