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]

Reply via email to