Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
Network API call (AV:N), no special conditions (AC:L), requires a valid OAuth2 token so PR:L, no user interaction post-consent; high C and I via profile/email/repo writes, no availability impact since deletion is scoped to the user's own repos.
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:L/UI:N/S:U/C:H/I:H/A:N
Lifecycle Timeline
2DescriptionCVE.org
Summary
Gitea 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(<token>:x-oauth-basic) and perform write actions, including modifying profiles, adding email addresses, creating repositories, and deleting repositories as the authorizing user.
Details
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:
// services/auth/basic.go
if uid != 0 {
store.GetData()["LoginMethod"] = OAuth2TokenMethodName
store.GetData()["IsApiToken"] = true // scope is NOT set
return u, nil
}The scope enforcement middleware in routers/api/v1/api.go exits early when ApiTokenScope is absent:
// routers/api/v1/api.go - tokenRequiresScopes
scope, scopeExists := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
if ctx.Data["IsApiToken"] != true || !scopeExists {
return //<- exits without checking scope, all actions permitted
}When 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.
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.
PoC
- Create an OAuth2 application in Gitea.
- Authorize it as a normal user with scope
read:useronly. - Take the resulting access token and call a write endpoint both ways:
Bearer | correctly blocked:
Authorization: Bearer <token>
PATCH /api/v1/user/settings -> 403 ForbiddenBasic | bypass:
Authorization: Basic base64(<token>:x-oauth-basic)
PATCH /api/v1/user/settings -> 200 OKAll verified bypass endpoints using a read:user-only token:
| Endpoint | Bearer | Basic |
|---|---|---|
PATCH /api/v1/user/settings | 403 | 200 |
POST /api/v1/user/emails | 403 | 200 |
POST /api/v1/user/repos | 403 | 200 |
PATCH /api/v1/repos/{owner}/{repo} | 403 | 200 |
DELETE /api/v1/repos/{owner}/{repo} | 403 | 200 |
The 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.
Impact
Any 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:
- Modify the victim's profile and settings
- Add attacker-controlled email addresses to the victim's account
- Create repositories as the victim
- Modify or delete the victim's private repositories
The entire OAuth2 scope system is effectively bypassed for any token submitted via Basic auth.
AnalysisAI
OAuth2 scope enforcement bypass in Gitea <= 1.26.1 allows any OAuth2 access token to perform write actions far beyond its granted scope when submitted via HTTP Basic authentication instead of as a Bearer token. A token issued with only read:user can modify user settings, add attacker-controlled emails, and create or delete the user's repositories, effectively nullifying the entire OAuth2 scope model for Basic-auth requests. No public exploit identified at time of analysis, but the advisory itself contains a full working PoC.
Technical ContextAI
Gitea is a self-hosted Git service written in Go. The flaw lives in services/auth/basic.go, which authenticates OAuth2 access tokens passed through the HTTP Basic auth path but never populates the ApiTokenScope key in the request context. The downstream middleware tokenRequiresScopes in routers/api/v1/api.go short-circuits and returns without checking any scope whenever ApiTokenScope is absent, so all API actions are permitted. This is a CWE-284 (Improper Access Control) issue: scope metadata that is correctly attached on the Bearer-token code path is silently dropped on the Basic-auth code path, producing inconsistent authorization enforcement for the same credential. The affected package is pkg:go/code.gitea.io_gitea.
RemediationAI
Vendor-released patch: upgrade Gitea to 1.26.2 or later, as published in GHSA-9r5x-wg6m-x2rc (https://github.com/go-gitea/gitea/security/advisories/GHSA-9r5x-wg6m-x2rc). If immediate patching is not possible, the most effective compensating control is to disable the OAuth2 provider feature in app.ini ([oauth2] ENABLED = false) so no scope-limited OAuth2 tokens exist that could be abused - note this breaks any third-party application integrations that rely on Gitea as an OAuth2 identity provider. As an alternative, audit and revoke existing OAuth2 application authorizations via Site Administration so untrusted apps cannot retain tokens, and consider fronting the API with a reverse proxy rule that strips or rejects Authorization: Basic headers on /api/v1/ (this will also break legitimate username/password and personal-access-token Basic auth use, so weigh the operational impact). Until upgrade, treat any previously issued OAuth2 token as equivalent to a full-write user PAT for the authorizing user.
Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r
Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp
The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir
Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea
Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec
models/repo_mirror.go in Gitea before 1.7.6 and 1.8.x before 1.8-RC3 mishandles mirror repo URL settings, leading to rem
An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita
Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab
Open Redirect on login in GitHub repository go-gitea/gitea prior to 1.16.5. Rated medium severity (CVSS 6.1), this vulne
Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any
Branch-protection bypass in Gitea's self-hosted Git server (all versions before 1.26.0) allows a user with push access t
Migration transport protections in Gitea are bypassed for Git LFS operations, affecting all self-hosted instances before
Same weakness CWE-284 – Improper Access Control
View allSame technique Authentication Bypass
View allVendor StatusVendor
SUSE
Severity: Important| Product | Status |
|---|---|
| SUSE Linux Enterprise Server 16.1 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Affected |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Affected |
| openSUSE Leap 15.5 | Affected |
| openSUSE Leap 15.6 | Affected |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-41640
GHSA-9r5x-wg6m-x2rc