Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAttacker sets OIDC picture claim to internal URL
-
DeliveryAuthenticates via configured OAuth2/OIDC source
-
ExploitGitea invokes oauth2UpdateAvatarIfNeed() on login
-
ExecutionUnrestricted http.Get() issues outbound request
-
PersistServer reaches loopback, RFC1918, or cloud metadata endpoint
-
ImpactBlind SSRF probes internal network or partially retrieves image-format response via avatar storage
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 | Exploitation requires three specific conditions to hold simultaneously: (1) |
| Impact | The CVSS 3.1 base score of 3.1 (AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N) correctly captures the limited baseline impact - blind SSRF with no direct data return path and high attack complexity due to the IdP |
| Exploit ScenarioDerived | An attacker with a low-privileged account authenticates to Gitea via a configured OAuth2/OIDC source backed by an IdP they control or can manipulate, setting their |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Jul 21, 2026
Blind server-side request forgery in Gitea's OAuth2 avatar synchronization path allows a low-privileged authenticated user to force the server to issue arbitrary outbound HTTP GET requests to attacker-controlled URLs. Gitea versions prior to 1.27.0, when configured with [oauth2_client] UPDATE_AVATAR = true, call Go's unrestricted http.Get() on the OIDC picture claim without applying the hostmatcher.NewDialContext restrictions used elsewhere in the codebase - enabling requests to loopback, RFC1918, and cloud metadata addresses such as 169.254.169.254. No active exploitation is confirmed in CISA KEV, but a functional proof-of-concept is included in the vendor advisory, and the fix is available in Gitea v1.27.0.
RemediationAI
Vendor-released patch: Gitea v1.27.0, available at https://github.com/go-gitea/gitea/releases/tag/v1.27.0. The fix is implemented in PRs #38406 (https://github.com/go-gitea/gitea/pull/38406) and #38426 (https://github.com/go-gitea/gitea/pull/38426), which apply hostmatcher.NewDialContext-based host filtering to the OAuth2 avatar fetch path via the unified ALLOWED_HOST_LIST configuration. If immediate upgrade is not feasible, the most direct compensating control is setting UPDATE_AVATAR = false under [oauth2_client] in app.ini, which disables the vulnerable code path entirely with no side effect other than preventing automatic avatar synchronization from OAuth2/OIDC providers. As a secondary layer, network egress filtering at the host or container level to block the Gitea process from reaching 169.254.169.254, RFC1918 ranges, and loopback addresses reduces SSRF impact but does not eliminate the vulnerability and may interfere with legitimate internal service connectivity. Advisory: https://github.com/go-gitea/gitea/security/advisories/GHSA-x77v-q46j-393g.
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
The vulnerable sink is oauth2UpdateAvatarIfNeed() in routers/web/auth/oauth.go, which invokes Go's default http.Get(url) on the AvatarURL field sourced from the OAuth2/OIDC provider's goth.User struct - commonly populated from the OIDC picture claim in the userinfo endpoint or ID token. CWE-918 (Server-Side Request Forgery) applies: the server makes outbound requests on behalf of an attacker without validating the destination host. Critically, Gitea's own repository migration code uses hostmatcher.NewDialContext to enforce TCP-level allow-listing, but this protection was absent from the OAuth2 avatar path until v1.27.0. The fix (PRs #38406 and #38426) moves the ALLOWED_HOST_LIST configuration to a shared scope covering both webhooks and OAuth2 client fetches. Affected package: pkg:go/code.gitea.io_gitea versions < 1.27.0.
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:H/PR:L/UI:N/S:U/C:L/I:N/A:N
Network vector for OAuth2 login flow; AC:H because attacker must control their own IdP picture claim; PR:L for required low-privileged account; C:L for blind SSRF with limited partial response retrieval; no integrity or availability impact.
Primary rating from Vendor (https://github.com/go-gitea/gitea).
CVSS VectorVendor: https://github.com/go-gitea/gitea
DescriptionCVE.org
Summary
When [oauth2_client] UPDATE_AVATAR = true is enabled, Gitea fetches the avatar URL received from an OAuth2/OIDC provider using Go's default HTTP client. The URL comes from the user's OAuth/OIDC avatar value, commonly the OIDC picture claim.
The affected code path calls http.Get(url) without applying outbound host or IP restrictions. A low-privileged user who can influence their own picture claim under an already-configured OAuth2/OIDC source can cause the Gitea server to make arbitrary outbound HTTP GET requests. This includes requests to loopback addresses, RFC 1918 private network addresses, and IPv4 link-local addresses such as 169.254.169.254.
This is a blind SSRF by default. Impact can increase in deployments where the Gitea host can reach cloud metadata services, localhost-only services, or internal services that return valid image data.
Details
The vulnerable sink is in routers/web/auth/oauth.go:
func oauth2UpdateAvatarIfNeed(ctx *context.Context, url string, u *user_model.User) {
if setting.OAuth2Client.UpdateAvatar && len(url) > 0 {
resp, err := http.Get(url)
if err == nil {
defer func() { _ = resp.Body.Close() }()
}
if err == nil && resp.StatusCode == http.StatusOK {
data, err := io.ReadAll(io.LimitReader(resp.Body, setting.Avatar.MaxFileSize+1))
if err == nil && int64(len(data)) <= setting.Avatar.MaxFileSize {
_ = user_service.UploadAvatar(ctx, u, data)
}
}
}
}The caller is in routers/web/auth/oauth_signin_sync.go:
func oauth2SignInSync(ctx *context.Context, authSourceID int64, u *user_model.User, gothUser goth.User) {
oauth2UpdateAvatarIfNeed(ctx, gothUser.AvatarURL, u)
...
}gothUser.AvatarURL is derived from the OAuth2/OIDC provider's avatar value. For OIDC providers, this is commonly populated from the picture claim returned by the provider's userinfo endpoint or ID token.
The issue is that this value can be attacker-influenced in some common IdP configurations, while Gitea fetches it server-side using http.Get with no host/IP validation and no restricted transport.
Comparable outbound fetch paths in Gitea use hostmatcher.NewDialContext to enforce restrictions at TCP dial time. For example, repository migration uses an HTTP transport with host matching. The OAuth2 avatar synchronization path does not apply those restrictions.
PoC
Requirements
- Local Gitea build or binary
- Python 3
- Python packages:
requests,pyjwt,cryptography - Gitea configured with OAuth2 avatar synchronization enabled
Install Python dependencies:
python3 -m pip install requests pyjwt cryptographyConfigure app.ini:
[oauth2_client]
UPDATE_AVATAR = true
ENABLE_AUTO_REGISTRATION = true
USERNAME = useridRun the fake OIDC provider:
python3 fake_oidc.py http://127.0.0.1:8888/ 9999Run a listener for the SSRF target:
nc -lvnp 8888Register an OAuth2 authentication source in Gitea:
- Provider:
OpenID Connect - Client ID:
gitea-client - Client Secret:
gitea-secret - OpenID Connect Auto Discovery URL:
http://127.0.0.1:9999/.well-known/openid-configuration
Then initiate login through the configured OAuth2 source.
Observed request to the SSRF listener:
GET / HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Go-http-client/1.1
Accept-Encoding: gzipObserve that Gitea fetched the OIDC picture claim URL from the server side using the default Go HTTP client.
Impact
When [oauth2_client] UPDATE_AVATAR = true is enabled, a low-privileged OAuth2/OIDC user who can influence their own picture claim can force the Gitea server to make outbound HTTP GET requests to attacker-selected URLs. This allows blind SSRF from the Gitea server’s network position, including requests to loopback addresses, RFC1918 private addresses, link-local addresses such as 169.254.169.254, and other internal services that may not be reachable from the public internet. In practical terms, this can enable internal service probing and interaction with localhost-only or private-network services depending on the deployment’s network access controls.
The vulnerability is blind in the common case because non-image responses such as HTML, JSON, or plaintext are rejected during avatar processing and are not directly returned to the attacker. However, impact can increase in cloud or internal-network deployments where metadata services, internal admin panels, monitoring endpoints, or image-generating internal services are reachable from the Gitea host. If an internal endpoint returns a valid supported image format within the configured avatar size limit, the response may be stored as the attacker’s avatar, creating a limited response retrieval primitive.
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
EUVD-2026-58134
GHSA-x77v-q46j-393g
NVD
CVE.org
EPSS
Exploit-DB