🛡️ CVE-2026-58441 — gitea.dev

⚪ Unknown ✅ No Known Exploit CWE-918 OSV
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Gitea: SSRF in restore-repo via unsanitized pull_request.yml Head.CloneURL

Summary

Gitea's restore-repo CLI command restores a repository from a dump

directory/archive. When parsing pull_request.yml from that dump, the

Head.CloneURL field is used to add a git remote and fetch from it with

no validation, because the safety check that's supposed to guard it

(CheckAndEnsureSafePR) is called with an empty commonCloneBaseURL,

which silently disables it. This lets a malicious dump make the Gitea

server execute git fetch against an attacker-chosen URL (SSRF), or

disclose a local git repository via file://. This is a different root

cause from the recently fixed path-traversal issue in the same command

(#38215), which patched DownloadURL/PatchURL but not Head.CloneURL.

Details

services/migrations/restore.go's GetPullRequests() unmarshals

pull_request.yml directly into base.PullRequest structs with no

validation of Head.CloneURL:

```go

err = yaml.Unmarshal(bs, &pulls)

...

for _, pr := range pulls {

if pr.PatchURL != "" {

pr.PatchURL = "file://" + util.FilePathJoinAbs(r.baseDir, pr.PatchURL)

}

CheckAndEnsureSafePR(pr, "", r) // <-- empty baseURL

}

```

CheckAndEnsureSafePR (services/migrations/common.go) is supposed to

reject Head.CloneURL/PatchURL values that don't share a common base

URL:

```go

func hasBaseURL(toCheck, baseURL string) bool {

if len(baseURL) > 0 && baseURL[len(baseURL)-1] != '/' {

baseURL += "/"

}

return strings.HasPrefix(toCheck, baseURL)

}

func CheckAndEnsureSafePR(pr *base.PullRequest, commonCloneBaseURL string, g base.Downloader) bool {

valid := true

if pr.PatchURL != "" && !hasBaseURL(pr.PatchURL, commonCloneBaseURL) {

pr.PatchURL = ""

valid = false

}

if pr.Head.CloneURL != "" && !hasBaseURL(pr.Head.CloneURL, commonCloneBaseURL) {

pr.Head.CloneURL = ""

valid = false

}

return valid

}

```

strings.HasPrefix(anything, "") is always true in Go. Because

restore.go is the only caller that passes "" as

commonCloneBaseURL, this check is a complete no-op on the restore-repo

path — Head.CloneURL survives unchanged regardless of its value. Every

other downloader (github.go, gitlab.go, gitea_downloader.go,

codebase.go, codecommit.go, onedev.go) passes a real base URL, so

they are not affected.

services/migrations/gitea_uploader.go then uses the unvalidated value

directly:

```go

err := g.gitRepo.AddRemote(remote, pr.Head.CloneURL, true)

// ... later: fetch from that remote

```

resulting in the server executing git fetch against an

attacker-controlled URL sourced from the dump file.

RCE via git's ext:: transport helper was tested and ruled out — a

normal git install rejects it by default (`fatal: transport 'ext' not

allowed`), independent of Gitea's own configuration. This report is

scoped to SSRF and local git-repository disclosure.

Confirmed present, byte-for-byte identical, in v1.26.4 (latest stable

tag), release/v1.27, and main, by direct checkout and diff.

PoC

1. Create a dump directory following the normal restore-repo layout

(repo.yml, etc.), and add a pull_request.yml containing at least

one entry with:

```yaml

  • number: 1

head:

cloneURL: "http://<attacker-controlled-or-internal-host>:<port>/ssrf-proof"

ref: "main"

```

2. Run gitea restore-repo against that dump directory for any repo

owner.

3. Observe on the target host/listener: an actual git HTTP

discovery request arrives, e.g.

GET /ssrf-proof/info/refs?service=git-upload-pack, driven entirely

by the value from the dump file.

Verified the core mechanism (steps 2–3, i.e. the unvalidated

Head.CloneURL surviving CheckAndEnsureSafePR("") and then being used

in a real git remote add + git fetch) with a minimal, standalone Go

program built from the verbatim, unmodified hasBaseURL /

CheckAndEnsureSafePR function bodies (attached: gitea_ssrf_poc.go),

run end-to-end against a local HTTP listener. The listener's access log

confirms the request actually arrives.

Impact

An attacker who can get an administrator to run gitea restore-repo

against a malicious dump (the same threat model already accepted for the

just-fixed path-traversal issue in this command, #38215) can make the

Gitea server issue a git fetch against an arbitrary attacker-chosen

URL. This allows:

  • SSRF against internal-only services or cloud metadata endpoints

reachable from the Gitea host.

  • Disclosure of local git repositories reachable via file:// paths

readable by the Gitea process.

No public disclosure planned. Happy to provide further detail on

request.

How this vulnerability can be exploited

This issue can be reached with local access to the system, attack complexity is low, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is changed, meaning a successful attack can affect components beyond the vulnerable one. Rated impact: confidentiality high, integrity none, availability none.

Weakness class

CVE-2026-58441 is classified as CWE-918: Server-Side Request Forgery (SSRF). The server fetches a URL supplied by the caller, which can be pointed at internal systems it alone can reach.

Affected software

CVE-2026-58441 is recorded against 2 packages.

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

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

References

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

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
CWE CWE-918
Public Exploit ✅ No
Source OSV
Published 2026-07-21
Updated 2026-08-12
Modified 2026-07-27
Fix URL N/A

Affected Packages

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

Similar Threats

Free Vulnerability Check

Is your site affected by CVE-2026-58441?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-58441 and other known CVE records.

Scan My Site Free →

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.