Skip to main content

Boteraser | Website and Server Security Solutions

🛡️ CVE-2026-58435 — gitea.dev

🟡 CVSS 5.4 — Medium ✅ No Known Exploit CWE-266 NVD
5.4
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Gitea LFS Deploy-Key Privilege Escalation

Vulnerability Header

| Field | Value |

| ------------------- | ----------------------------------------------------------- |

| Vulnerability Title | Gitea LFS Deploy-Key Privilege Escalation |

| Severity Rating | High |

| Bug Category | Insufficient Authorization |

| Location | services/lfs/server.go:268, routers/private/serv.go:275 |

| Affected Versions | 1.25.5 |

Executive Summary

Gitea's LFS server (services/lfs/server.go:268) uses the UserID embedded in an LFS JWT to make cross-repository authorization decisions via LFSObjectAccessible(). This would be safe if the JWT UserID always matched the actual requesting principal — but for deploy keys, routers/private/serv.go:275 sets UserID = repo.OwnerID instead of any identity representing the deploy key itself. As a result, an attacker who holds a write deploy key for any single repo owned by a victim can obtain a legitimate JWT (via the standard SSH git-lfs-authenticate flow) that Gitea will honor as if the victim themselves were making the request. The attacker can then exfiltrate LFS objects from any private repo the victim owns — no admin credentials, no server secrets, no brute force required. If the victim is a site administrator, every LFS object on the entire Gitea instance is reachable. Deploy keys exist precisely to grant narrow, single-repo access to CI/CD systems; this vulnerability defeats that isolation entirely for LFS data.

Root Cause Analysis

Technical Description

The vulnerability is a trust-boundary confusion across two independent subsystems. When a deploy key authenticates over SSH, serv.go sets UserID = repo.OwnerID because the code has no better representation for a deploy key identity (a FIXME comment acknowledges this). That UserID is baked verbatim into the LFS JWT by cmd/serv.go. The JWT is then consumed by server.go, which treats claims.UserID as the authenticated principal and loads that user object as ctx.Doer. When the batch upload handler encounters an object that exists on disk but isn't yet linked to the target repo, it calls LFSObjectAccessible(ctx, ctx.Doer, oid) — a global query across all repos the claimed user can see — to decide whether to silently create the cross-repo link. The JWT's RepoID claim is verified (so the request is correctly scoped to one repo at the HTTP level), but the UserID driving the cross-repo access decision is the repo *owner*, not the deploy key. The attacker ends up holding a valid, server-signed token that impersonates the victim for any LFS authorization check.

First Faulty Condition

The primary bug — where the JWT UserID is set incorrectly — is in serv.go:

| File | routers/private/serv.go |

| --------- | ------------------------------------------------------------------------------------------------- |

| Line | 275 |

| Condition | Deploy key branch sets results.UserID = repo.OwnerID; the owner's UID is embedded in the JWT and later used as the authenticated principal for cross-repo privilege decisions in server.go:268 |

```go

// routers/private/serv.go:252–278

if key.Type == asymkey_model.KeyTypeDeploy {

...

// FIXME: Deploy keys aren't really the owner of the repo pushing changes

// however we don't have good way of representing deploy keys in hook.go

// so for now use the owner of the repository

results.UserName = results.OwnerName

results.UserID = repo.OwnerID // ← OWNER's UID, not the deploy key

...

}

```

The secondary bug — where the tainted UserID is actually misused — is in server.go:

| File | services/lfs/server.go |

| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| Line | 268 |

| Condition | LFSObjectAccessible(ctx, ctx.Doer, oid) makes a cross-repo decision using the JWT UserID, which for deploy keys is the repo owner, not the deploy key holder |

```go

// services/lfs/server.go:267–275

if exists && meta == nil {

accessible, err := git_model.LFSObjectAccessible(ctx, ctx.Doer, p.Oid)

...

if accessible {

_, err := git_model.NewLFSMetaObject(ctx, repository.I

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs low-level privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality low, integrity low, availability none.

CVSS metrics in full

The score comes from this vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N

  • Attack vector: Network — reachable from anywhere that can route to the service.
  • Attack complexity: Low — the attack works reliably, with no preparation.
  • Privileges required: Low — an ordinary user account is enough.
  • User interaction: None — nobody has to be tricked into anything.
  • Scope: Unchanged — the damage stays inside the vulnerable component.
  • Confidentiality impact: Low — limited, and the attacker does not choose what is affected.
  • Integrity impact: Low — limited, and the attacker does not choose what is affected.
  • Availability impact: None.

Weakness class

CVE-2026-58435 is classified as CWE-266: Incorrect Privilege Assignment. A product incorrectly assigns a privilege to a particular actor, creating an unintended sphere of control for that actor.

Affected software

CVE-2026-58435 is recorded against 3 packages.

  • code.gitea.io/gitea
  • gitea.dev
  • unknown

Timeline and source

Published on 21 July 2026 and last revised on 27 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Package)
github.com (Web)

Other advisories for this package

code.gitea.io/gitea has other advisories on record. If you are patching this one, these are worth checking on the same host:

Same weakness in other software

These advisories are the same class of weakness (CWE-266: Incorrect Privilege Assignment) in other software:

Details

Severity Medium
CVSS Score 5.4
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
CWE CWE-266
Public Exploit ✅ No
Source NVD
Published 2026-07-21
Updated 2026-08-20
Modified 2026-07-27
Fix URL N/A

Affected Packages

Software From version Fixed in
code.gitea.io/gitea — —
gitea.dev — —
unknown — —

Similar Threats

Vulnerability Monitoring

Track new vulnerabilities in gitea.dev

CVE-2026-58435 is rated CVSS 5.4 Medium. BotEraser monitors your WordPress installation and notifies you when software you use appears in our vulnerability database.

Set Up Free Alerts →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026
✓