Algorithmic Complexity DoS in musl libc `iconv` GB18030 Decoder — CVE-2026-6042
by jensnesten · 2026-07-05
- Severity
- High
- CVE
- CVE-2026-6042
- Category
- network
- Affected product
- musl libc — iconv implementation (GB18030 and EUC-KR decoders)
- Affected versions
- Confirmed on musl 1.2.5 (Alpine 3.21) and musl 1.2.6 (built from source); likely all musl versions since GB18030/UHC/CP949 support was introduced
- Disclosed
- 2026-07-05
- Patch status
- unpatched
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-04 |
| Author / Researcher | jensnesten |
| CVE / Advisory | CVE-2026-6042 |
| Category | network |
| Severity | High |
| CVSS Score | 7.5 (CVSS 3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, per source repository) |
| Status | PoC |
| Tags | musl, libc, iconv, denial-of-service, algorithmic-complexity, gb18030, alpine-linux |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | musl libc — iconv implementation (GB18030 and EUC-KR decoders) |
| Versions Affected | Confirmed on musl 1.2.5 (Alpine 3.21) and musl 1.2.6 (built from source); likely all musl versions since GB18030/UHC/CP949 support was introduced |
| Language / Platform | C (musl libc internals); PoC harness in C, containerized with Alpine Linux/Docker |
| Authentication Required | No |
| Network Access Required | Yes — any network-facing musl-based service that transcodes untrusted GB18030/EUC-KR input via iconv() is exploitable remotely. The source repo explicitly disputes advisory metadata that labels the attack vector as local, noting it is “obviously network, not local.” |
Summary
musl libc’s GB18030 4-byte decoder (src/locale/iconv.c) contains a gap-skipping loop that, for each decoded character, iterates the entire 23,940-entry gb18030[126][190] lookup table to resolve a linear index to a Unicode codepoint. A crafted 4-byte sequence (82 35 8F 33) lands just below the dense CJK Unified Ideographs block, forcing the loop to “chase” through roughly 20,902 dense entries, each scanning the full table — approximately 500 million comparisons per decoded character. Because cost scales linearly with the number of adversarial characters, a few hundred bytes of crafted input can pin a CPU core for tens of minutes. The PoC includes both a standalone timing harness and a minimal HTTP server that transcodes POST bodies through iconv(), demonstrating the vulnerability is reachable over the network on any Alpine/musl-based service that processes user-supplied non-UTF-8 text.
Vulnerability Details
Root Cause
The GB18030 4-byte decoder in musl (iconv.c, roughly lines 434-442) converts a 4-byte input sequence into a linear index, then walks a “gap-skipping” loop to map that index onto a real Unicode codepoint by subtracting out mapped 2-byte sequences it passes along the way. For codepoints that land just below the dense CJK Unified Ideographs range (U+4E00–U+9FBD, ~20,902 entries), the loop must step through the entire dense region one entry at a time, and for every step it re-scans the entire gb18030[126][190] table (23,940 entries) to determine which entries fall within the current sliding range. This produces roughly O(k^2) work (k ≈ 24,000) per decoded character, and O(n * k^2) for n adversarial characters. The same gap-skipping pattern exists in the EUC-KR extended Hangul decoder (iconv.c:514-522) against the smaller ksc[93][94] table (8,742 entries).
Attack Vector
- Attacker identifies (or assumes) a network-facing service running on a musl-based system (Alpine Linux, Void Linux, postmarketOS, minimal containers) that calls
iconv()to transcode untrusted input declared as GB18030 or EUC-KR. - Attacker crafts a payload of repeated 4-byte sequences such as
82 35 8F 33, each of which decodes to a linear index (19,171) just below the dense CJK block. - Attacker sends the payload to the service (e.g., as an HTTP POST body with
Content-Type: text/plain; charset=gb18030). - The service’s call to
iconv()for each adversarial character burns ~0.26 seconds of CPU time (measured on Alpine 3.21 / musl 1.2.5); as few as 5 characters (20 bytes) takes over a second, 100 characters (400 bytes) takes ~26 seconds, and 10,000 characters (40 KB) can pin a core for ~43 minutes. - Repeating the request (optionally across multiple connections/threads) exhausts available worker threads/processes or CPU capacity, denying service to legitimate users.
Impact
Any musl-based system running a service that transcodes GB18030 or EUC-KR from user-supplied input via iconv() is vulnerable to a low-bandwidth, high-amplification denial-of-service. A single crafted request of a few hundred bytes can consume minutes of CPU time on a single core, and because the payload is tiny, the attack is easy to replicate across many connections/threads to exhaust an entire host or container fleet. This is particularly relevant to Alpine Linux-based container images, which are extremely common as lightweight bases for web services, APIs, and microservices.
Environment / Lab Setup
Target: Alpine Linux (musl 1.2.5 or 1.2.6) container running a service that calls iconv() on
user-controlled input declared as GB18030 or EUC-KR (simulated here by server.c, a
minimal HTTP server exposed via Docker on port 8080)
Attacker: Any HTTP client (curl) capable of sending a POST request with a custom Content-Type
charset parameter and a crafted binary body; Docker to build/run the vulnerable target
Proof of Concept
PoC Script
See
poc_gb18030_dos.c(standaloneiconv()timing PoC) andserver.c(HTTP server attack-surface simulation) in this folder.
| |
poc_gb18030_dos.c times iconv() conversion of benign vs. adversarial GB18030 byte sequences and reports the slowdown factor and projected times for larger inputs. server.c builds a minimal HTTP server (packaged via the included Dockerfile) that transcodes POST bodies through iconv() and reports elapsed transcode time in an X-Transcode-Time response header; test.sh automates sending benign and adversarial payloads to that server and comparing response times.
Detection & Indicators of Compromise
Example: HTTP response header showing an anomalously long transcode time
X-Transcode-Time: 5.234871
Server-side log line (as emitted by the included PoC server):
[request] charset=gb18030 bodylen=20 ... done in 5.234s (status 200)
Signs of compromise:
- A single small request (tens to low hundreds of bytes) causes disproportionate CPU usage or response latency on a musl/Alpine-based service.
- Elevated CPU utilization on worker processes/threads correlated with requests declaring
charset=gb18030orcharset=euc-kr(or equivalent) with no corresponding increase in request volume or payload size. - Thread/worker pool exhaustion or request timeouts under low request-rate conditions.
Remediation
| Action | Detail |
|---|---|
| Primary fix | No vendor patch confirmed as of 2026-07-05. Reported to the musl project via the oss-security mailing list (2026-04-09); track upstream musl releases for a fix to the GB18030/EUC-KR gap-skipping decoder logic. |
| Interim mitigation | Avoid calling iconv() on untrusted, attacker-controlled input for GB18030/EUC-KR without strict size/rate limits; enforce per-request CPU/time budgets or timeouts around transcoding operations; consider using glibc-based images instead of musl-based images for services that must transcode these charsets from untrusted sources; apply WAF/reverse-proxy rules to cap body size and reject anomalous non-UTF-8 charset declarations where not functionally required. |
References
Notes
Mirrored from https://github.com/jensnesten/CVE-2026-6042-PoC on 2026-07-05.
| |