Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Requires a valid low-scope personal access token, so PR:L not PR:N; endpoint only serves read-only archives, so C:H but I:N and A:N.
Primary rating from Vendor (https://github.com/go-gitea/gitea).
CVSS VectorVendor: https://github.com/go-gitea/gitea
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
Lifecycle Timeline
6DescriptionCVE.org
Summary
PR #37698 added checkDownloadTokenScope to /raw/*, /media/*, and attachment download web endpoints. The /archive/* endpoint (repo.Download in routers/web/repo/repo.go:372) was not included in the fix. This endpoint accepts OAuth2 tokens via webAuth.AllowOAuth2 (registered at routers/web/web.go:1649-1652) but does not call checkDownloadTokenScope or CheckRepoScopedToken.
A personal access token with any non-repository scope (e.g., read:issue or read:misc) can download full repository archives (zip/tar.gz) of private repositories the token owner has access to.
Impact
Scope escalation: tokens scoped to non-repository categories can access full repository content through the archive download endpoint. Higher impact than endpoints fixed in #37698 because /archive/* serves the entire repository.
Steps to Reproduce
- Create a personal access token with ONLY read:misc scope
- Access: GET /{owner}/{private-repo}/archive/main.tar.gz
- Archive is served (200 OK) instead of being rejected (403 Forbidden)
Compare with fixed endpoints:
- GET /{owner}/{private-repo}/raw/branch/main/README.md correctly returns 403
Root Cause
Download function in routers/web/repo/repo.go:372 does not call checkDownloadTokenScope. The outer group middleware reqUnitCodeReader checks repository permission but not token scope.
The API equivalent (/api/v1/repos/{owner}/{repo}/archive/*) IS properly scoped via tokenRequiresScopes(AccessTokenScopeCategoryRepository). The git HTTP endpoints are scoped via CheckRepoScopedToken in httpBase.
Suggested Fix
Add checkDownloadTokenScope(ctx) to Download and InitiateDownload in routers/web/repo/repo.go. The function already exists in routers/web/repo/download.go (same package).
Discovery Method
Variant analysis of PR #37698 - reviewed all web routes with webAuth.AllowOAuth2 middleware.
AnalysisAI
{owner}/{repo}/archive/* accepts OAuth2 tokens but never validates the token's scope, unlike the equivalent API and git-HTTP paths. The issue was found via variant analysis of prior fix PR #37698, is fixed in 1.26.2, and carries a low EPSS (0.26%, 17th percentile) with no public exploit identified at time of analysis beyond the reproduction steps published in the GHSA advisory.
Technical ContextAI
Gitea is a lightweight, self-hosted Go-based Git hosting service (package pkg:go/code.gitea.io/gitea). Gitea implements fine-grained personal access token (PAT) scopes so a token can be limited to categories such as issues, notifications, or misc data without granting repository code access. The web archive route (repo.Download at routers/web/repo/repo.go:372, registered at routers/web/web.go:1649-1652) is wrapped by webAuth.AllowOAuth2 to accept PAT bearer tokens and by the reqUnitCodeReader middleware, which verifies the user's repository permission but NOT the token's declared scope. The root cause is CWE-863 (Incorrect Authorization): the download handler omits the checkDownloadTokenScope enforcement that PR #37698 added to /raw/*, /media/*, and attachment endpoints, and does not call CheckRepoScopedToken as the git HTTP paths do or tokenRequiresScopes(AccessTokenScopeCategoryRepository) as the API archive path does. The authorization decision therefore checks the account's access but skips the token-scope check, allowing scope escalation.
RemediationAI
Vendor-released patch: upgrade to Gitea 1.26.2 or later, which adds checkDownloadTokenScope to the Download and InitiateDownload/RedirectDownload handlers per PR #37735 (https://github.com/go-gitea/gitea/pull/37735); see the release notes at https://blog.gitea.com/release-of-1.26.2/ and the advisory GHSA-cr4g-f395-h25h. If immediate upgrade is not possible, reduce exposure by revoking or not issuing personal access tokens with non-repository scopes to users who should not read private repository code, and by placing a reverse proxy or WAF rule that blocks or requires additional auth on GET/POST /{owner}/{repo}/archive/* requests bearing bearer tokens - note this proxy control also blocks legitimate token-based archive downloads and must whitelist trusted automation. Auditing which accounts hold private-repo access and rotating existing low-scope tokens further limits residual risk until the upgrade is applied.
Same weakness CWE-863 – Incorrect Authorization
View allSame technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-41612
GHSA-cr4g-f395-h25h