Skip to main content

Gitea EUVDEUVD-2026-58172

| CVE-2026-58445 LOW
Observable Discrepancy (CWE-203)
2026-07-21 https://github.com/go-gitea/gitea GHSA-pgqf-926r-548m
2.7
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
    Authenticate as any Gitea user
  2. Delivery
    Obtain write:issue token on attacker-controlled repository
  3. Exploit
    Send DELETE /api/v1/repos/{own-repo}/issues/{id}/labels/{target_id}
  4. Execution
    Observe 204 (label exists anywhere on instance) vs. 422 (does not exist)
  5. Persist
    Iterate sequential label IDs
  6. Impact
    Enumerate instance-wide label population across tenant boundaries

Vulnerability Assessment

Weakness
CWE
ASVS 5.0
V6 - Authentication Timing-safe comparisons
Exploitation Conditions

The attacker must be an authenticated Gitea user holding write:issue permission on at least one repository they control, and must have network access to the Gitea REST API. No special server configuration, non-default feature, or administrative privilege is required - the vulnerability is present in the default API behavior of all Gitea instances through v1.26.3. Exploitation is bounded by what the oracle reveals: only label ID existence (boolean, per ID) is leaked; label names, colors, repository names, content, and owning organization are not disclosed, and no cross-repository write occurs. Unauthenticated users or users with no repository (and thus no write:issue scope) cannot exploit this. The practical constraint is that automated sequential scanning over a large ID space would generate significant API log entries, making large-scale enumeration detectable.

Impact

The provided CVSS 3.1 base score of 2.7 (AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N) understates real-world exploitability: the vendor assigned PR:H, but any regular authenticated Gitea user holding write:issue on any repository they own - a standard, user-level permission - can trigger the oracle without administrative access, suggesting PR:L is more appropriate (raising the base score to approximately 4.3). The impact remains narrow: only label ID existence is leaked, with no names, colors, repository names, or content exposed, and no write side-effects. The vulnerability is absent from the CISA KEV catalog, and EPSS data is not provided; given the authentication prerequisite and minimal leaked information, widespread exploitation is unlikely. The primary real-world risk is on multi-tenant public Gitea instances where untrusted users can probe the label ID space of private repositories belonging to other tenants. Single-tenant or closed-registration instances face negligible incremental exposure. The existence of a researcher-verified PoC means exploit difficulty is essentially zero for any valid Gitea account holder.

Exploit ScenarioDerived

A working proof of concept was verified against Gitea v1.26.3 by the reporter. An authenticated attacker (bob) with write:issue on any repository they control sends DELETE /api/v1/repos/bob/pub/issues/1/labels/{target_id} with sequential label IDs; a 204 response confirms the label ID exists somewhere on the instance (including in alice's private repository), while a 422 confirms it does not. Iterating IDs from 1 upward enumerates the entire instance label population across all tenant boundaries without any access to the target repositories.

Monitor Track and reassess. Why: LOW severity (CVSS 0.1-3.9).
Patch available 0.1% exploitation probability (EPSS)

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

Alert me

AnalysisAIv1 – Jul 21, 2026

Cross-repository label-ID enumeration oracle in Gitea through v1.26.3 allows any authenticated user with write:issue permission on any repository to probe label ID existence across all repositories and organizations on the instance - including private ones they cannot access. The flaw arises because the DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} API handler performs a global, unscoped label lookup and leaks existence via differential HTTP status codes (204 vs. 422). No label names, colors, repository associations, or content are disclosed, and no cross-repository writes occur; however, a working proof of concept was verified against v1.26.3 and a fix is available in v1.27.0. No public exploit identified at time of analysis beyond the verified PoC in the advisory.

RemediationAI

Upgrade Gitea to v1.27.0 or later; this release scopes the label lookup in DeleteIssueLabel to the URL repository (or its owning organization), mirroring all sibling handlers, so the HTTP status no longer distinguishes cross-tenant label existence. See the advisory at https://github.com/go-gitea/gitea/security/advisories/GHSA-pgqf-926r-548m and the release at https://github.com/go-gitea/gitea/releases/tag/v1.27.0. If immediate patching is not feasible, operators can restrict API access to trusted users only by disabling public registration (reducing the attacker pool to known accounts) or placing the Gitea API behind an authentication proxy; neither eliminates the oracle for existing authenticated users but reduces exposure surface. There is no configuration toggle that disables only the DeleteIssueLabel endpoint without patching.

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 self-hosted Git service written in Go (package: go/code.gitea.io/gitea). The vulnerable handler, DeleteIssueLabel in routers/api/v1/repo/issue_label.go, calls issues_model.GetLabelByID - implemented as a bare e.ID(labelID).Get(l) ORM query with no repo_id or org_id filter in models/issues/label.go. Every sibling handler (GetLabel, EditLabel, DeleteLabel for both repo and org contexts) correctly uses scoped variants GetLabelInRepoByID or GetLabelInOrgByID, returning 404 for foreign label IDs. DeleteIssueLabel is the sole outlier. The downstream service layer (issue_service.RemoveLabel) only validates the doer's write permission on the issue's own repository and never checks that the label belongs to that repository. The root cause is CWE-203 (Observable Discrepancy): differential HTTP responses (204 No Content on global ID hit; 422 ErrLabelNotExist on miss) expose a side-channel. Because label IDs are sequential auto-increments, an attacker can trivially enumerate the entire instance-wide label population with linear scanning.

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 2.7 LOW
AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N
vuln.today AI 4.3 MEDIUM

Any authenticated user with standard write:issue on their own repo can exploit the oracle, making PR:L more accurate than vendor's PR:H; no integrity or availability impact applies.

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

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
High
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
None
Availability
None

DescriptionCVE.org

Summary

The API endpoint DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} loads the label by ID with a global, unscoped lookup and never verifies the label belongs to the URL's repository (or its owning organization). Because the response status differs by whether the label ID exists anywhere on the instance (204) versus not (422), an authenticated user can use the endpoint as a cross-repository label-ID existence / enumeration oracle, including for labels in repositories and organizations they cannot access.

Severity

  • The leaked information is minimal (existence/count of label IDs instance-wide); **no label name, color, or owning

repository is disclosed, and no cross-repository write occurs.**

Affected / patched versions

  • Affected: through 1.26.3 (latest at time of report).
  • Patched: none yet.

Details

DeleteIssueLabel resolves the label with a global loader and never checks its scope:

go
// routers/api/v1/repo/issue_label.go  (DeleteIssueLabel)
label, err := issues_model.GetLabelByID(ctx, ctx.PathParamInt64("id"))   // global, unscoped

GetLabelByID (models/issues/label.go) is e.ID(labelID).Get(l) with no repo_id / org_id filter. The handler never verifies label.RepoID == ctx.Repo.Repository.ID (nor the org-label equivalent), and the downstream issue_service.RemoveLabel (services/issue/label.go) only re-checks the doer's write permission on the issue's own repository - never that the label belongs to it.

Every sibling label handler is correctly scoped - GetLabel / EditLabel / DeleteLabel (repo and org) use GetLabelInRepoByID / GetLabelInOrgByID and return 404 for a foreign ID. DeleteIssueLabel is the only outlier.

Why it is only an oracle: deleteIssueLabel (models/issues/issue_label.go) deletes the issue_label row keyed by (issue.ID, label.ID). For a foreign label, no such row exists → the function returns early before any mutation or comment creation. So there is no cross-repo write and no leak of the label's name. But the HTTP status differs:

  • label ID exists anywhere on the instance (incl. private repos/orgs) → 204 No Content
  • label ID does not exist → 422 (ErrLabelNotExist)

Label IDs are sequential auto-increment, so this enumerates the instance-wide label population and probes existence of specific IDs across tenant boundaries.

Proof of Concept

Verified end-to-end on a build of the v1.26.3 tag.

  • alice (private repo alice/secret) creates a label → internal id 1.
  • Attacker bob (separate user; public repo bob/pub with issue #1; no access to alice/secret) holds a token

with write:issue on his own repo.

text
bob DELETE /api/v1/repos/bob/pub/issues/1/labels/1          -> HTTP 204   (alice's PRIVATE label id exists)
bob DELETE /api/v1/repos/bob/pub/issues/1/labels/99999999   -> HTTP 422   (no such label)

Differing only by the label ID: 204 vs 422 distinguishes "label ID exists" from "does not exist." bob has zero rights to alice/secret but can still learn label id 1 exists. (Alice's label is untouched - no write.)

Reproduction steps:

  1. Create two users alice, bob. As alice, create a private repo and a label on it (note the label id from

the API response).

  1. As bob, create any repo with an issue, and a token with write:issue.
  2. curl -u bob:$T -X DELETE https://<gitea>/api/v1/repos/bob/pub/issues/1/labels/<alice_label_id> → 204.
  3. curl -u bob:$T -X DELETE https://<gitea>/api/v1/repos/bob/pub/issues/1/labels/99999999 → 422.
  4. The differing status across an ID bob cannot otherwise see is the oracle.

Impact

Cross-tenant authorization-key bypass producing a label-ID existence/enumeration oracle: an authenticated user can determine whether arbitrary label IDs (including in private repositories and organizations they cannot access) exist, and enumerate the instance-wide label population.

Remediation

Scope the loader like every sibling handler, returning 404 for a label that is not in the URL repository (or its owning organization), so the status no longer distinguishes existence:

go
// routers/api/v1/repo/issue_label.go - in DeleteIssueLabel, after loading the label
if label.RepoID != ctx.Repo.Repository.ID && label.OrgID != ctx.Repo.Repository.OwnerID {
    ctx.APIErrorNotFound()
    return
}

(Equivalently, resolve via GetLabelInRepoByID and, for org repositories, also accept the repo owner's org labels - mirroring the scoping in GetLabel/EditLabel/DeleteLabel.)

Threat Intelligence Overview

EPSS Score
0.1%
Top 96% exploitable
Prevalence
Medium
popular self-hosted Git platform across enterprises and development teams
Threat Intel
1
1 source
Data Quality
5 sources
Confidence: Medium

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 LOW
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
LOW severity (CVSS 0.1-3.9)
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
Defer
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
No
Human Impact· derived
Low

Priority Score

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

Attack Technique

Information disclosure occurs when an application unintentionally exposes sensitive data that aids attackers in reconnaissance or directly compromises security.

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

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