Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59248

CVE-2026-59248: Cowlib HPACK/QPACK DoS Vulnerability

CVE-2026-59248 is a denial of service flaw in ninenines cowlib that allows remote attackers to exhaust memory via malformed HTTP/2 or HTTP/3 requests. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-59248 Overview

CVE-2026-59248 is an unbounded resource allocation vulnerability [CWE-770] in ninenines/cowlib, the HTTP parser library used by Cowboy, RabbitMQ's management plugin, and other Erlang and Elixir HTTP/2 and HTTP/3 stacks. The flaw resides in the HPACK and QPACK prefixed-integer decoder cow_hpack_common:dec_big_int/3, which reads continuation octets without enforcing a limit on count, bit width, or resulting value. An unauthenticated remote peer can send a crafted HEADERS frame that forces the Erlang virtual machine to allocate hundreds of megabytes of transient bignum data, exhausting memory and denying service. The issue affects cowlib from version 2.0.0 before 2.19.0.

Critical Impact

A single malicious HTTP/2 or HTTP/3 request from an unauthenticated peer can drive the Erlang VM to memory exhaustion, taking down any exposed server or client built on cowlib.

Affected Products

  • ninenines/cowlib from version 2.0.0 before 2.19.0
  • Cowboy HTTP server (uses cowlib as its HTTP parser)
  • RabbitMQ management plugin and other Erlang/Elixir HTTP/2 or HTTP/3 servers and clients depending on cowlib

Discovery Timeline

  • 2026-07-28 - CVE-2026-59248 published to NVD
  • 2026-07-28 - Last updated in NVD database

Technical Details for CVE-2026-59248

Vulnerability Analysis

The defect lives in cow_hpack_common:dec_big_int/3 inside src/cow_hpack_common.hrl, invoked from cow_hpack:decode/2 (src/cow_hpack.erl) and cow_qpack:decode_field_section/3 (src/cow_qpack.erl). The decoder implements the RFC 7541 prefixed-integer encoding used by HPACK and QPACK. It reads continuation octets until it encounters one with the high bit clear, evaluating Int + (Value bsl M) at each step and growing the shift M by seven bits per octet.

No limit is enforced on the number of continuation octets processed, on the resulting bit width, or on the accumulated integer value. The decoder consumes whatever encoded length the peer supplies. This is a classic algorithmic-complexity denial-of-service vector amplified by Erlang's runtime semantics.

Root Cause

Erlang integers are immutable. Each intermediate Value bsl M and each accumulator update allocates a fresh bignum whose digit width grows linearly with the number of octets processed so far. Summed across the full decode, transient bignum digit materialization is on the order of the square of the encoded length. A single maximal HPACK indexed representation delivered inside one HTTP/2 HEADERS frame plus one CONTINUATION frame at Cowboy's default max_frame_size_received can force hundreds of megabytes of transient allocation and garbage-collection churn before the resulting header-table index is rejected as invalid.

Attack Vector

An unauthenticated remote HTTP/2 or HTTP/3 peer transmits a HEADERS frame containing a prefixed-integer field whose continuation-octet chain is arbitrarily long. Repeated or concurrent connections multiply the memory pressure and drive the Erlang VM toward exhaustion. Any exposed endpoint that accepts HPACK or QPACK from an untrusted peer is reachable.

text
%% Security patch in src/cow_hpack_common.hrl - hard limit for HPACK integer decoding
%% The HPACK format has 4 different integer prefixes length (from 4 to 7)
%% and each can be used to create an indefinite length integer if all bits
%% of the prefix are set to 1.
%%
%% We hard limit indefinite length integers to 38bits. The maximum
%% possible value is large enough for normal use cases and does
%% not produce an Erlang big int.

dec_int5(<<2#11111:5, Rest/bits>>) ->
    dec_big_int(Rest, 31, 0);

Source: GitHub Commit for cowlib

The patch caps the indefinite-length integer at 38 bits, which is large enough for legitimate HPACK use cases while preventing the Erlang runtime from allocating a big integer. The accompanying test asserts that a 32,768-octet continuation chain is rejected under a constrained max_heap_size.

Detection Methods for CVE-2026-59248

Indicators of Compromise

  • Sudden Erlang VM memory growth on Cowboy, RabbitMQ management, or other cowlib-dependent processes without a corresponding increase in legitimate request throughput
  • HTTP/2 HEADERS or CONTINUATION frames from a single peer containing prefixed-integer fields with unusually long continuation-octet chains (dozens or more octets of 0xFF)
  • beam.smp process crashes or OOM-killer terminations correlated with inbound HTTP/2 or HTTP/3 traffic
  • Elevated garbage-collection activity and scheduler stalls in the Erlang VM during header decoding

Detection Strategies

  • Inspect HTTP/2 and HTTP/3 frames at the proxy or WAF layer and reject HEADERS payloads containing prefixed integers whose continuation chains exceed a small octet budget (for example, 8 octets)
  • Monitor Erlang VM telemetry (erlang:memory/0, scheduler utilization, GC counts) and alert on rapid growth tied to specific remote peers
  • Correlate connection-level metrics such as HEADERS frame size at max_frame_size_received with per-peer memory consumption

Monitoring Recommendations

  • Enable process-level memory limits using Erlang's max_heap_size flag so a runaway decode terminates the offending process rather than the VM
  • Ship Cowboy and RabbitMQ logs plus Erlang VM metrics to a centralized platform such as Singularity Data Lake for correlation with network telemetry and per-peer connection patterns
  • Track HTTP/2 and HTTP/3 protocol errors and connection resets by source address to identify probing behavior

How to Mitigate CVE-2026-59248

Immediate Actions Required

  • Upgrade cowlib to version 2.19.0 or later in all Cowboy, RabbitMQ, and Erlang or Elixir services that expose HTTP/2 or HTTP/3
  • Audit dependency trees for transitive cowlib pins below 2.19.0 in rebar.config, mix.exs, and vendored builds
  • Restrict exposure of HTTP/2 and HTTP/3 endpoints to trusted networks until the upgrade is deployed

Patch Information

The fix is committed to the cowlib repository at f582430498072a0c65ad338030321576dc13a343, which introduces a hard 38-bit cap in dec_big_int and adds a regression test that rejects a 32,768-octet continuation chain under a constrained max_heap_size. See the GitHub Commit for cowlib, the CNA Security Advisory, and the OSV Vulnerability Report for full details.

Workarounds

  • Place an HTTP/2-aware reverse proxy in front of cowlib-based services and enforce a strict HEADERS frame size limit well below max_frame_size_received
  • Lower Cowboy's max_frame_size_received and per-connection header limits to constrain the maximum encoded length reachable by a single peer
  • Apply Erlang max_heap_size process flags on request-handling processes so a runaway decode kills the process instead of exhausting the VM
bash
# Update cowlib dependency (rebar3 project)
rebar3 upgrade cowlib

# Or pin the fixed version in rebar.config
# {cowlib, "2.19.0"}

# Elixir / mix.exs
# {:cowlib, "~> 2.19.0", override: true}
mix deps.update cowlib

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.