Sep 25, 2026·8 min read·4 visits
Unbounded variable-length integer decoding in the python-hyper/hpack library enables unauthenticated remote attackers to trigger 100% CPU exhaustion and Denial of Service via malformed HTTP/2 frame headers.
CVE-2026-59980 is a CPU exhaustion vulnerability in python-hyper/hpack, where an unauthenticated remote attacker can trigger an infinite loop or high computational complexity overhead by sending a crafted HTTP/2 stream containing excessive variable-length integer continuation octets.
The python-hyper/hpack library is the standard Python implementation of the HTTP/2 Header Compression (HPACK) protocol, defined in RFC 7541. This library is integrated into ASGI servers, HTTP/2 application frameworks, and HTTP/2 clients to parse compressed HTTP headers. Because headers represent the initial entry point for processing incoming HTTP requests, any flaw in the decompression engine exposes a direct, unauthenticated network-facing attack surface.
CVE-2026-59980 identifies an uncontrolled resource consumption vulnerability (CWE-400) within the variable-length integer parsing mechanism of the HPACK decoder. Specifically, the library fails to restrict the quantity of continuation octets it processes when decoding HPACK-encoded integers. When processing a malformed stream containing highly padded integer representations, the decoder enters an expensive computation loop that exhibits quadratic algorithmic complexity relative to input size.
The resulting resource exhaustion causes the executing Python thread or process to consume 100% CPU. Because many Python application deployments rely on a single-threaded execution model or a limited worker pool, a single unauthenticated HTTP/2 frame can completely deny service to the underlying application. This vulnerability impacts all installations of the python-hyper/hpack library prior to version 4.2.0.
To compress headers efficiently, RFC 7541 specifies a prefix-based, variable-length integer representation. This format uses an N-bit prefix within the first octet of the stream. If the integer is smaller than 2^N - 1, it is fully contained within the prefix. If the integer is equal to or greater than 2^N - 1, all prefix bits are set to 1, and the remainder of the integer is encoded as a series of seven-bit blocks across subsequent continuation octets.
For each continuation octet, the most significant bit (MSB) acts as a continuation flag. An MSB of 1 indicates that another octet follows, while an MSB of 0 indicates the final octet of the integer. RFC 7541 explicitly instructs implementations to enforce limits on the value and octet length of integer encodings to prevent implementation-specific resource limits from being exceeded.
The root cause of CVE-2026-59980 is that the decode_integer function in src/hpack/hpack.py did not enforce any upper limit on the number of continuation octets. Because Python transparently manages arbitrary-precision integers (bignums), there is no hardware-level register overflow to terminate the loop or trigger an exception. Instead, the decoder continues to parse continuation octets, repeatedly performing bit-shift and addition operations.
As the parsed integer value grows larger, the computational overhead of these bignum operations increases. For an input sequence of length N continuation octets, the system must perform arithmetic operations on integers whose bit length scales linearly with N. This behavior translates to O(N^2) computational complexity, transforming a routine decoding operation into a runaway CPU loop that blocks the thread until exhaustion occurs.
Prior to the release of version 4.2.0, the decoding loop inside src/hpack/hpack.py was implemented without bounds checks on the number of processed octets. The loop parsed incoming data continuously until an octet with an MSB of 0 was encountered, or until an IndexError occurred due to reaching the end of the byte stream.
# Vulnerable implementation of decode_integer in src/hpack/hpack.py
def decode_integer(data: bytes | memoryview, prefix_bits: int) -> tuple[int, int]:
# ... prefix calculations ...
value = limit
shift = 0
index = 1
try:
while True:
byte = data[index]
index += 1
value += (byte & 127) << shift # Unbounded bit shift & addition on Python bignum
if (byte & 128) == 0:
break
shift += 7
except IndexError as err:
msg = f"Unable to decode HPACK integer representation from {data!r}"
raise HPACKDecodingError(msg) from errThe patch introduces a hard limit on the number of continuation octets, defined by the constant VARINT_MAX_LENGTH = 5. Five octets provide 35 bits of capacity, which is sufficient to encode any standard 32-bit unsigned integer while protecting the engine from excessive bignum calculations. If the byte-offset index exceeds this maximum length during the parsing loop, the decoder aborts operation immediately by raising an HPACKDecodingError.
# Patched implementation in src/hpack/hpack.py
VARINT_MAX_LENGTH = 5 # octets, enough for encoding prefix + uint32
def decode_integer(data: bytes | memoryview, prefix_bits: int) -> tuple[int, int]:
# ... prefix calculations ...
value = limit
shift = 0
index = 1
try:
while True:
byte = data[index]
index += 1
value += (byte & 127) << shift
if (byte & 128) == 0:
break
shift += 7
if index > VARINT_MAX_LENGTH: # Enforce limit to block runaway bignum loops
msg = f"Variable integer representation is too long: {data!r}"
raise HPACKDecodingError(msg)The introduction of VARINT_MAX_LENGTH restricts the execution of the loop to a maximum of five iterations per integer representation. This effectively bounds the computational complexity to O(1) for any individual integer, mitigating the quadratic performance degradation. The fix is complete for its intended scope, preventing uncontrolled loop execution while remaining compliant with RFC 7541 requirements.
Exploiting CVE-2026-59980 requires the ability to send standard HTTP/2 frames to a vulnerable target application server. The attacker does not need authentication or specialized system permissions. The primary requirement is that the target server utilizes a Python-based HTTP/2 server stack, such as hyper-h2, which depends on the hpack library to parse compressed request headers.
The attack vector operates by crafting a malicious HTTP/2 frame, such as a HEADERS or PUSH_PROMISE frame. The frame payload is structured to trigger the HPACK integer decoding loop. The attacker begins by setting the prefix-bits of the initial octet to the maximum value (e.g., 5 prefix bits set to 31, representing 0x1F). This informs the parser that the integer value continues in subsequent bytes.
The attacker then appends a large sequence of continuation octets where the high-order bit (MSB) is set to 1. For example, a sequence of thousands of 0xFF bytes is appended. Because each 0xFF byte has its high bit set, the decode_integer loop continues to execute. With every iteration, the Python interpreter dynamically allocates memory and performs arithmetic operations on an increasingly large arbitrary-precision integer.
A single connection sending a frame with 50,000 continuation octets will force the target thread into a CPU-bound loop lasting several seconds or minutes. Because of Python's Global Interpreter Lock (GIL), this CPU-intensive operation can block execution across other threads in the same process, multiplying the impact. An attacker can send multiple concurrent requests to consume all available worker processes on the host.
The security impact of CVE-2026-59980 is primarily focused on system availability. Successful exploitation allows an unauthenticated remote attacker to induce a complete Denial of Service (DoS) of the target web application. By sending a small, highly compressed payload, the attacker causes disproportionate CPU consumption on the backend server, achieving high asymmetric leverage.
The vulnerability is rated with a CVSS v4.0 score of 6.3 (Medium). The score reflects a high impact on Availability (VA:L on a single instance, but easily scalable to total service disruption in multi-tenant environments) and low Attack Complexity (AC:L). No user interaction or prior system privileges are required to exploit the flaw.
The EPSS score for this vulnerability is 0.00301, representing a low immediate probability of active exploitation in the wild. No active exploitation has been reported in the CISA Known Exploited Vulnerabilities (KEV) catalog. However, because the proof of concept is highly reliable and straightforward to implement, any directly exposed application running an unpatched version remains at risk of trivial denial-of-service attacks.
The definitive resolution for CVE-2026-59980 is upgrading the hpack library to version 4.2.0 or later. This version introduces the explicit limit of five continuation octets and raises an HPACKDecodingError when the threshold is exceeded. System administrators should verify downstream dependencies, such as h2, to ensure they pull in the updated version of hpack.
If patching the library immediately is not feasible, infrastructure-level mitigations can protect vulnerable applications. Placing a robust, hardened reverse proxy, such as Nginx, HAProxy, or an enterprise-grade Web Application Firewall (WAF), in front of the Python application is highly effective. These proxies terminate incoming HTTP/2 TLS connections and parse headers using highly optimized, memory-safe engines that enforce strict length boundaries.
For environments where proxy-level termination is not available, runtime network monitoring should be employed to flag anomalous HTTP/2 traffic. Snort or Suricata IDS rules can be configured to detect HTTP/2 frame payloads containing excessive repetitive sequences of octets with the MSB set. However, because the payload is typically encrypted via TLS, network-level detection must occur at the TLS termination endpoint.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
hpack python-hyper | >= 1.0.0, < 4.2.0 | 4.2.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network |
| CVSS v4.0 Score | 6.3 |
| EPSS Score | 0.00301 (20.30% percentile) |
| Impact | Denial of Service (CPU Exhaustion) |
| Exploit Status | Proof of Concept |
| CISA KEV Status | Not Listed |
Uncontrolled Resource Consumption
CVE-2026-57231 is a high-severity vulnerability in the Podman container engine. When executing a container from a crafted OCI or Docker image, malformed environment variable entries lacking an equals separator can trigger an unexpected behavior in the spec generation parser. This vulnerability enables a container image to silently exfiltrate host environment variables into the running container workspace, exposing high-privilege credentials and sensitive runtime secrets.
CVE-2026-74480 is a critical memory safety vulnerability in the Linux kernel's network bridge multicast routing subsystem (net: bridge) resulting from a Use-After-Free (UAF) condition during fast-leave processing of IGMP/MLD multicast groups.
CVE-2026-21992 is a critical, unauthenticated remote code execution (RCE) vulnerability affecting the REST WebServices component of Oracle Identity Manager (OIM) and the Web Services Security component of Oracle Web Services Manager (OWSM). Exploitation occurs over standard network protocols without user interaction, enabling a complete compromise of target system infrastructure.
An insecure configuration in the diagnostic HTTP server of @rsdoctor/rspack-plugin allowed unauthenticated remote attackers or malicious local websites to retrieve serialized build metadata and full source code modules.
The PHP email processing library zbateson/mail-mime-parser is vulnerable to multiple algorithmic complexity exploits. By submitting small, highly structured email payloads, remote, unauthenticated attackers can trigger high CPU utilization or out-of-memory states, causing an application-wide denial of service.
CVE-2026-61815 is a high-severity Carriage Return / Line Feed (CRLF) header injection vulnerability in the zbateson/mail-mime-parser library. Due to incomplete sanitization logic, encoded newline sequences within filenames and headers survive parsing and translate into literal CRLF control bytes. When applications process or forward these payloads, the library writes the unescaped control bytes directly into outbound SMTP metadata, allowing remote attackers to inject rogue headers or compromise message integrity.