Skip to main content

Gitea EUVDEUVD-2026-58168

| CVE-2026-58441 MEDIUM
Server-Side Request Forgery (SSRF) (CWE-918)
2026-07-21 https://github.com/go-gitea/gitea GHSA-xmj7-xj85-hfc3
6.3
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. Recon
    Craft pull_request.yml with attacker-controlled cloneURL
  2. Delivery
    Package as valid restore-repo dump archive
  3. Exploit
    Deliver dump to Gitea administrator
  4. Install
    Admin runs gitea restore-repo on server host
  5. C2
    CheckAndEnsureSafePR called with empty baseURL, bypassing all URL validation
  6. Execute
    Gitea executes git remote add and git fetch against attacker URL
  7. Impact
    SSRF reaches internal services or file:// discloses local git repos

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V4 - API and Web Service URL allowlisting, SSRF prevention
MITRE ATT&CK

2 techniques across 2 tactics: Initial Access, Credential Access

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

Exploitation Conditions

The gitea restore-repo CLI command must be executed by a Gitea administrator on the server host, processing a dump directory that the attacker controls or has tampered with. The dump must contain a pull_request.yml file with at least one pull request entry whose head.cloneURL field is set to the attacker's target URL. For SSRF exploitation, the Gitea server process must have outbound network connectivity to the target host. For file:// local repository disclosure, the target path must be readable by the OS user running the Gitea process. No special Gitea configuration, feature flags, or non-default settings are required - the vulnerability exists in the default code path of the restore command. Exploitation is limited by the requirement for an administrator to actively run the CLI command (UI:R per CVSS), meaning the attacker must deliver a malicious dump and socially engineer admin execution. RCE via git's ext:: transport is explicitly not achievable because standard git installations reject that transport by default, independent of Gitea configuration.

Impact

The provided CVSS 3.1 score of 6.3 (Medium) with vector AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N is internally consistent: the attack vector is local (CLI invocation on the Gitea server host), complexity is low once triggered, no attacker privileges are required, but an administrator must actively run the restore command (UI:R). The scope change (S:C) reflects that SSRF reaches services beyond the Gitea process boundary, and confidentiality impact is high given access to cloud metadata endpoints or internal services. The primary real-world friction is the social engineering prerequisite - an attacker must convince a Gitea administrator to run restore-repo against a malicious dump, which is the same threat model accepted for the previously fixed path-traversal issue in the same command. For organizations that run restore-repo as part of migration or backup workflows, or accept dump archives from third parties, the exploitability is meaningfully higher. A PoC is publicly documented with step-by-step instructions and a standalone Go proof-of-concept, lowering the barrier to exploitation. EPSS data was not provided in the input. No CISA KEV listing is present. In cloud-hosted Gitea deployments, SSRF against http://169.254.169.254/ or equivalent metadata endpoints could yield credentials enabling significant lateral movement, making the practical impact exceed the Medium CVSS score in those environments.

Exploit ScenarioDerived

An attacker crafts a minimal Gitea dump directory containing a pull_request.yml with head.cloneURL set to http://169.254.169.254/latest/meta-data/iam/security-credentials/ (the AWS IMDSv1 endpoint). The dump is delivered to a Gitea administrator under the guise of a legitimate repository migration from a partner organization. When the administrator runs gitea restore-repo --repo-dir <dump>, the Gitea process executes git fetch against the metadata endpoint, and the cloud provider returns an HTTP response to the git protocol handshake containing IAM role credentials. A publicly documented PoC with a standalone Go program confirming the full AddRemote/fetch path is included in GHSA-xmj7-xj85-hfc3.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.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

Server-Side Request Forgery in Gitea's restore-repo CLI command allows an attacker who can supply a malicious dump archive to a Gitea administrator to force the server to issue git fetch against arbitrary attacker-controlled or internal URLs, including cloud metadata endpoints and local filesystem paths via file://. The root cause is a Go language logic defect: CheckAndEnsureSafePR is invoked with an empty commonCloneBaseURL string, causing strings.HasPrefix(anything, "") to always return true, which silently disables the URL validation guard for Head.CloneURL in the restore path only. A detailed PoC is publicly documented in the GHSA advisory; no CISA KEV listing is present, indicating active exploitation is unconfirmed at time of analysis. Fix is available in Gitea v1.27.0.

RemediationAI

Upgrade Gitea to v1.27.0 or later, which resolves the missing URL validation in the restore-repo path. The release is available at https://github.com/go-gitea/gitea/releases/tag/v1.27.0. If immediate upgrade is not feasible, restrict execution of the gitea restore-repo CLI command to a minimal set of trusted operators and enforce that all dump archives originate from trusted, internally generated sources only - do not accept dump archives from external or untrusted parties. As a network-level compensating control, configure egress firewall rules on the Gitea host to block outbound connections to RFC-1918 address ranges, link-local addresses (169.254.0.0/16), and loopback, which limits the SSRF impact surface by preventing cloud metadata endpoint access; note this does not mitigate file://-based local repository disclosure. Auditing or pre-validating pull_request.yml files within dump archives before running restore-repo can also detect malicious head.cloneURL values, though this requires manual inspection. The advisory is GHSA-xmj7-xj85-hfc3.

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

The affected component is Gitea's repository migration/restore subsystem, specifically services/migrations/restore.go and services/migrations/common.go. When gitea restore-repo processes a dump archive, it unmarshals pull_request.yml into base.PullRequest structs and then calls CheckAndEnsureSafePR(pr, "", r) - passing an empty string as the commonCloneBaseURL parameter. The guard function hasBaseURL uses strings.HasPrefix(toCheck, baseURL) which in Go always evaluates to true when baseURL is an empty string, making the entire safety check a no-op for this call site. All other downloaders (github.go, gitlab.go, gitea_downloader.go, codebase.go, codecommit.go, onedev.go) pass a real base URL, so they are unaffected. The unvalidated Head.CloneURL value is then passed directly to g.gitRepo.AddRemote() and subsequently used in a live git fetch, triggering outbound network requests to attacker-specified destinations. CWE-918 (Server-Side Request Forgery) accurately describes the root cause class. The affected package is code.gitea.io/gitea (Go module). RCE via git's ext:: transport was tested and ruled out by the reporter, as standard git installations reject that transport by default. This is a distinct root cause from the previously patched path-traversal issue in #38215, which addressed DownloadURL/PatchURL but left Head.CloneURL unguarded.

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

AV:L because exploitation requires local CLI execution on the Gitea host; S:C because SSRF extends impact to internal network services and cloud metadata endpoints beyond the Gitea process.

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

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

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

Attack Vector
Local
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

DescriptionCVE.org

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"
  1. Run gitea restore-repo against that dump directory for any repo

owner.

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

Threat Intelligence Overview

EPSS Score
0.1%
Top 95% exploitable
Prevalence
Medium
self-hosted git forge used by organizations not on GitHub/GitLab
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 MEDIUM
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.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
Small
Automatable· derived
No
Human Impact· derived
Medium

Priority Score

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

Attack Technique

Server-Side Request Forgery exploits applications that fetch remote resources based on user-supplied URLs.

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

Severity: Moderate
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected

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