Skip to main content

Gitea CVE-2026-28699

HIGH
Improper Access Control (CWE-284)
2026-06-16 https://github.com/go-gitea/gitea GHSA-9r5x-wg6m-x2rc
8.1
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
8.1 HIGH
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
vuln.today AI
8.1 HIGH

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.

3.1 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 17, 2026 - 00:17 vuln.today
Analysis Generated
Jun 17, 2026 - 00:17 vuln.today

DescriptionGitHub Advisory

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:

go
// 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:

go
// 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

  1. Create an OAuth2 application in Gitea.
  2. Authorize it as a normal user with scope read:user only.
  3. Take the resulting access token and call a write endpoint both ways:

Bearer | correctly blocked:

Authorization: Bearer <token>
PATCH /api/v1/user/settings  ->  403 Forbidden

Basic | bypass:

Authorization: Basic base64(<token>:x-oauth-basic)
PATCH /api/v1/user/settings  ->  200 OK

All verified bypass endpoints using a read:user-only token:

EndpointBearerBasic
PATCH /api/v1/user/settings403200
POST /api/v1/user/emails403200
POST /api/v1/user/repos403200
PATCH /api/v1/repos/{owner}/{repo}403200
DELETE /api/v1/repos/{owner}/{repo}403200

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. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Attacker hosts malicious OAuth2 app
Delivery
Victim authorizes app with read:user scope
Exploit
Attacker captures access token
Execution
Re-encode token as Basic auth header
Persist
Call write API endpoints
Impact
Modify emails or delete victim repositories

Vulnerability AssessmentAI

Exploitation Requires the Gitea instance to have the OAuth2 provider feature enabled and at least one OAuth2 application registered and authorized by a target user, yielding a valid OAuth2 access token that the attacker controls (e.g., via operating a malicious OAuth2 app, phishing the authorization flow, or stealing an existing token). … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The CVSS 3.1 vector (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N, 8.1 High) accurately reflects a network-reachable, low-complexity bypass requiring an existing OAuth2 token (PR:L) with high confidentiality and integrity impact but no availability impact - the attacker cannot exceed the authorizing user's underlying permissions, so blast radius is bounded by that user's account and repositories. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario A user installs or authorizes a seemingly benign third-party OAuth2 application against the organization's Gitea instance, granting only `read:user` scope. The malicious application takes the issued access token, re-sends it as `Authorization: Basic base64(<token>:x-oauth-basic)` to `/api/v1/user/emails`, adds an attacker-controlled email, and then triggers a password reset to that address - or calls `DELETE /api/v1/repos/{owner}/{repo}` to destroy the victim's private repositories. …
Remediation 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). … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours: Audit all OAuth2 tokens in use in your Gitea deployment, document tokens with read-only or limited scopes, review access logs for suspicious write operations with low-privilege tokens, and disable HTTP Basic authentication for OAuth2 submissions if operationally feasible. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

Share

CVE-2026-28699 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy