Skip to main content

Gitea CVE-2026-23603

LOW
Server-Side Request Forgery (SSRF) (CWE-918)
2026-07-21 https://github.com/go-gitea/gitea GHSA-x77v-q46j-393g
3.1
CVSS 3.1 · GitHub Advisory

Severity by source

GitHub Advisory PRIMARY
3.1 LOW
AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
vuln.today AI
3.1 LOW

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.

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

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
None
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jul 21, 2026 - 21:11 vuln.today
Analysis Generated
Jul 21, 2026 - 21:11 vuln.today

DescriptionGitHub Advisory

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:

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:

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:

bash
python3 -m pip install requests pyjwt cryptography

Configure app.ini:

ini
[oauth2_client]
UPDATE_AVATAR = true
ENABLE_AUTO_REGISTRATION = true
USERNAME = userid

Run the fake OIDC provider:

bash
python3 fake_oidc.py http://127.0.0.1:8888/ 9999

Run a listener for the SSRF target:

bash
nc -lvnp 8888

Register 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:

http
GET / HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

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

AnalysisAI

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

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Attacker sets OIDC picture claim to internal URL
Delivery
Authenticates via configured OAuth2/OIDC source
Exploit
Gitea invokes oauth2UpdateAvatarIfNeed() on login
Execution
Unrestricted http.Get() issues outbound request
Persist
Server reaches loopback, RFC1918, or cloud metadata endpoint
Impact
Blind SSRF probes internal network or partially retrieves image-format response via avatar storage

Vulnerability AssessmentAI

Exploitation Exploitation requires three specific conditions to hold simultaneously: (1) `[oauth2_client] UPDATE_AVATAR = true` must be set in `app.ini` - this is not the default configuration and must be explicitly enabled; (2) at least one OAuth2 or OIDC authentication source must be configured and active in Gitea; and (3) the attacker must be able to control the `picture` claim value returned by the configured identity provider for their own account - this is possible with a self-hosted IdP, a provider permitting custom claims, or an attacker-operated fake OIDC endpoint. … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment 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 `picture` claim control requirement. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario 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 `picture` claim to `http://169.254.169.254/latest/meta-data/iam/security-credentials/`. Upon login, Gitea's server calls `http.Get()` on that URL from its own network position, issuing an unauthenticated HTTP request to the cloud instance metadata service; if the response is a valid image within the avatar size limit, it may be stored as the attacker's avatar, partially leaking the response. …
Remediation Vendor-released patch: Gitea v1.27.0, available at https://github.com/go-gitea/gitea/releases/tag/v1.27.0. … Detailed patch versions, workarounds, and compensating controls in full report.

Threat intelligence, references, and detailed analysis are available after sign-in.

More in Gitea

View all
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-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-2020-13246 HIGH POC
7.5 May 20

An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita

CVE-2022-0905 HIGH POC
7.1 Mar 10

Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab

CVE-2022-1058 MEDIUM POC
6.1 Mar 24

Open Redirect on login in GitHub repository go-gitea/gitea prior to 1.16.5. Rated medium severity (CVSS 6.1), this vulne

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-27780 CRITICAL
9.8 Jul 03

Branch-protection bypass in Gitea's self-hosted Git server (all versions before 1.26.0) allows a user with push access t

CVE-2026-26292 CRITICAL
9.8 Jul 03

Migration transport protections in Gitea are bypassed for Git LFS operations, affecting all self-hosted instances before

Share

CVE-2026-23603 vulnerability details – vuln.today

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