oss-sec mailing list archives

ngtcp2: qlog_parameters_set_transport_params_stack_overflow [CVE-2026-40170]


From: Alan Coopersmith <alan.coopersmith () oracle com>
Date: Fri, 17 Apr 2026 09:53:26 -0700

https://github.com/ngtcp2/ngtcp2/security/advisories/GHSA-f523-465f-8c8f advises:
qlog_parameters_set_transport_params_stack_overflow

tatsuhiro-t published GHSA-f523-465f-8c8f Apr 16, 2026

Package:           ngtcp2
Affected versions: <= 1.22.0
Patched versions:  1.22.1

Summary
-------
ngtcp2_qlog_parameters_set_transport_params() serializes transport parameters
into a fixed stack buffer (uint8_t buf[1024]) without complete bounds checks.

When qlog is enabled and peer-controlled transport parameters are large enough,
this causes a stack buffer overflow (ASAN confirmed).

Details
-------
1. The trigger starts in normal handshake processing.

   ngtcp2_conn_set_remote_transport_params sends peer transport parameters to
   qlog serialization at lib/ngtcp2_conn.c#L11670:

ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server,
                                            NGTCP2_QLOG_SIDE_REMOTE);

2. Inside ngtcp2_qlog_parameters_set_transport_params, JSON is built in a fixed
   stack buffer (buf[1024]) and a moving pointer p (lib/ngtcp2_qlog.c#L902,
   lib/ngtcp2_qlog.c#L905):

void ngtcp2_qlog_parameters_set_transport_params(...) {
  uint8_t buf[1024];
  uint8_t *p = buf;
  ...
}

3. The function then appends many peer-influenced fields
   (CID/token/preferred-address data/limits).

   Representative writes are visible at lib/ngtcp2_qlog.c#L1004 and
   lib/ngtcp2_qlog.c#L1006:

p = write_pair_cid(p, "initial_source_connection_id", &params->initial_scid);
...
p = write_pair_hex(p, "data", paddr->stateless_reset_token,
                   sizeof(paddr->stateless_reset_token));

4. There is no end-to-end guard that guarantees the full serialized output fits
   into buf.

   With sufficiently large combined field output, p advances beyond buf + 1024,
   and later helper writes become stack out-of-bounds writes.

5. The final write that actually crosses the boundary happens in the
   hex-encoding path used by qlog helpers.

   In write_hex (lib/ngtcp2_qlog.c#L58), the pointer is passed through to
   ngtcp2_encode_hex:

static uint8_t *write_hex(uint8_t *p, const uint8_t *data, size_t datalen) {
  *p++ = '"';
  p = ngtcp2_encode_hex(p, data, datalen);
  *p++ = '"';
  return p;
}

   Then ngtcp2_encode_hex (lib/ngtcp2_str.c#L51) writes bytes sequentially to
   dest:

uint8_t *ngtcp2_encode_hex(uint8_t *dest, const uint8_t *data, size_t len) {
  for (; len--;) {
    *dest++ = low[(size_t)(*data >> 4)];
    *dest++ = low[(size_t)(*data++ & 0x0f)];
  }
  return dest;
}

   Once p has already moved beyond buf + 1024, these writes become stack
   out-of-bounds writes. ASAN reports this as AddressSanitizer:
   stack-buffer-overflow and identifies buf in
   ngtcp2_qlog_parameters_set_transport_params as the overflowing object.

[See GHSA link for PoC]

Impact
------

Vulnerability type:

    Stack-based out-of-bounds write (CWE-121 / CWE-787)

Who is impacted:

    Deployments that enable qlog callback (qlog->write != NULL) and process
    untrusted peer transport parameters.

Patches
-------
ngtcp2 v1.22.1 fixes this vulnerability.

The following commit mitigates this vulnerability:

https://github.com/ngtcp2/ngtcp2/commit/708a7640c1f48fb8ffb540c4b8ea5b4c1dfb8ee5

Workarounds
-----------
Do not turn on qlog on client.

Severity:   High - 7.5 / 10
            CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CVE ID:     CVE-2026-40170
Weaknesses: CWE-121 Stack-based Buffer Overflow
Credits:    @Kherrisan Reporter


Current thread: