Hello Serf PMC, I am forwarding the report below to the Serf PMC after corresponding with [email protected].
Summary of the exchange: - I reported a remote heap buffer overflow in the HTTP/2 HPACK decoder in buckets/hpack_buckets.c to [email protected]. - Piotr P. Karwasz from ASF Security confirmed that the analysis is accurate: the growth condition in hpack_decode_buffer_ensure() (around lines 1230-1236) is inverted, so the 128-byte decode buffer is never enlarged, and hpack_read_bytes() can copy an oversized, attacker-influenced literal past the allocation. - He noted that Serf's HTTP/2 support, including this decoder, only exists in the unreleased trunk / 1.5.x line and has never appeared in a published Apache Serf release. On that basis, ASF Security decided the issue does not warrant a CVE or an out-of-band fix. - He suggested submitting it as a regular bug to the Serf JIRA: https://issues.apache.org/jira/projects/SERF/issues I would prefer not to create a JIRA account for this. Instead, I am forwarding the full report to the Serf PMC and the development list, so that a committer who works on buckets/hpack_buckets.c can review and, if appropriate, fix the defect directly. I understand and respect that unreleased code does not meet the criteria for a CVE. My request is simply that the code defect be reviewed and fixed before Serf 1.5.x is released, so downstream packagers and source-build users are not exposed. Technical summary: - Project: Apache Serf - Affected version: trunk branch / 1.5.x (HTTP/2 support) - Vulnerability type: Heap-based Buffer Overflow (remote) - CWE: CWE-122 / CWE-787 - File: buckets/hpack_buckets.c - Entry: protocols/http2_protocol.c:1314 (HEADERS/PUSH_PROMISE frame dispatch) - Call chain: protocols/http2_stream.c:694 serf_http2__stream_handle_hpack() -> protocols/http2_protocol.c:1325 / buckets/hpack_buckets.c:1194 serf__bucket_hpack_decode_create() -> buckets/hpack_buckets.c:1592 hpack_process() -> buckets/hpack_buckets.c:1755 hpack_read_bytes() (Sink) - Root cause: buckets/hpack_buckets.c:1233 `while (minsize < ctx->buffer_size)` should compare `minsize > ctx->buffer_size`; the buffer is therefore never grown. - Overflowing sink: buckets/hpack_buckets.c:1550 and buckets/hpack_buckets.c:1572. - Trigger: a remote HTTP/2 peer sends a HEADERS frame containing a literal header field (no-index or incremental indexing, new name) with a key/value length greater than 128 octets, delivered across multiple TCP segments so the underlying stream read returns a partial amount (129 <= len < required). ctx->header_allowed (HTTP2_MAX_HEADER_ENTRYSIZE = 0x20000) permits lengths up to ~128 KB, so the length check does not block the input. The partial read is then copied into the 128-byte ctx->buffer. - Payload form: an HPACK literal-header-field representation, e.g. first octet 0x00, followed by a 7-bit-prefixed length > 128, followed by the field bytes split over two TCP writes. - Suggested remediation: 1. Correct the growth condition in hpack_decode_buffer_ensure() to loop while `minsize > ctx->buffer_size` (or use `>=`). 2. Add an overflow guard on `buffer_size * 2`. 3. Bound the copy length in hpack_read_bytes() to the allocated buffer size. The original report I sent to [email protected], and the reply from Piotr P. Karwasz, are included below for full context. Please let me know if you would like me to provide anything further. Kind regards, Ho1aAs [email protected] ---------- Forwarded message --------- 发件人: ASF Security <[email protected]> Date: 2026年9月18日周五 20:27 Subject: Re: [SECURITY] Apache Serf - Remote Heap Buffer Overflow in HTTP/2 HPACK Decoder To: Ho1aAs <[email protected]> Hello Ho1aAs, Thank you for contacting [email protected]. Your analysis of buckets/hpack_buckets.c is accurate: the growth condition in hpack_decode_buffer_ensure() (around lines 1230-1236) is inverted, so the 128-byte decode buffer is never enlarged, and hpack_read_bytes() can then copy an oversized, attacker-influenced literal past the allocation. The same buffer-growth defect in the HTTP/2 HPACK decoder was reported to us earlier and has already been assessed. The key consideration is that Serf's HTTP/2 support — including this decoder — exists only in the unreleased trunk / 1.5.x line and has never appeared in a published Apache Serf release; the current releases are the 1.3.x series. On that basis the issue does not warrant a CVE or an out-of-band fix. Unless you find a similar issue in a released version, please submit it as a regular bug to: https://issues.apache.org/jira/projects/SERF/issues You can request a JIRA account here: https://selfserve.apache.org/jira-account.html Kind regards, Piotr P. Karwasz ASF Security On Fri, 18 Sep 2026 12:49:22 +0800, Ho1aAs <[email protected]> wrote: > ## Subject / Header > - Project Name: Apache Serf > - Affected Version: > *trunk branch*- Vulnerability Type: Heap-based Buffer Overflow (remote) > - CWE-ID: CWE-122 / CWE-787 > - CVSS v3.1 Vector: AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H > - CVSS Score: 8.1 (High) > > ## Vulnerability Summary > The HPACK decoder's dynamic buffer resize helper has an inverted loop > condition, so the read buffer is never enlarged beyond its initial 128 > bytes. When a peer sends an HPACK literal header field whose key or value > length exceeds 128 bytes, the subsequent `memcpy` copies the received bytes > into the fixed-size buffer without reallocation, corrupting adjacent heap > memory. Since header field data is fully controlled by the remote HTTP/2 > peer (server or MITM), this yields remote heap corruption on any Serf > client that negotiates HTTP/2. > > ## Affected Component & Call Chain > - File: `buckets/hpack_buckets.c` > - Entry: `protocols/http2_protocol.c:1314` (HEADERS/PUSH_PROMISE frame > dispatch) > - `protocols/http2_stream.c:694 serf_http2__stream_handle_hpack() -> > protocols/http2_protocol.c:1325 / buckets/hpack_buckets.c:1194 > serf__bucket_hpack_decode_create() -> buckets/hpack_buckets.c:1592 > hpack_process() -> buckets/hpack_buckets.c:1755 hpack_read_bytes() (Sink)` > - Root cause: `buckets/hpack_buckets.c:1233` — `while (minsize < > ctx->buffer_size)` should compare `minsize > ctx->buffer_size`; the buffer > is therefore never grown. > - Overflowing sink: `buckets/hpack_buckets.c:1550` and > `buckets/hpack_buckets.c:1572`. > > ## Trigger Scenario / Payload Overview > A remote HTTP/2 peer sends a HEADERS frame containing a literal header > field (no-index or incremental indexing, new name) with a key/value length > greater than 128 octets, delivered across multiple TCP segments so that the > underlying stream read returns a partial amount (129 <= len < required). > `ctx->header_allowed` (HTTP2_MAX_HEADER_ENTRYSIZE = 0x20000) permits > lengths up to ~128 KB, so the length check does not block the input. The > partial read is then copied into the 128-byte `ctx->buffer`. > > Payload form: an HPACK literal-header-field representation, e.g. first > octet `0x00`, followed by a 7-bit-prefixed length `> 128`, followed by the > field bytes split over two TCP writes. > > ## Impact & CVSS Justification > Remote heap buffer overflow with attacker-controlled length and contents, > reachable before any authentication, leading to memory corruption and > potential code execution or denial of service. AV:N (network peer), AC:H > (requires partial-read delivery, fully controllable by the peer), PR:N/UI:N > (client merely connects), and C/I/A:H justify 8.1. > > ## Suggested Remediation > Correct the growth condition in `hpack_decode_buffer_ensure()` to loop > while `minsize > ctx->buffer_size` (or use `>=`), and add an overflow guard > on `buffer_size * 2`. Additionally, bound the copy length in > `hpack_read_bytes()` to the allocated buffer size. > > > Reporter (Credit): > Ho1aAs <[email protected]> <[email protected]> > > Best regards, > > Ho1aAs > Email: [email protected]
