Oct 3, 2026·7 min read·1 visit
Praxis is vulnerable to HTTP/2 compression bombs and connection-stalling attacks, leading to rapid, unbound memory consumption and Denial of Service.
A critical vulnerability exists in the praxis-proxy library where the omission of default limits on HTTP/2 server options allows remote attackers to trigger a Denial of Service (DoS) using an HPACK compression bomb and flow-control window stalls. This vulnerability is cataloged as GHSA-cjcg-cxmh-9wcr.
The vulnerability identified as GHSA-cjcg-cxmh-9wcr details a severe Denial of Service (DoS) flaw within the Praxis proxy framework, specifically affecting the praxis-proxy crate. Praxis is an API proxy designed on top of Cloudflare's Pingora framework, engineered to handle high-throughput network routing. Under default configurations prior to version 0.5.2, the proxy fails to enforce restrictions on HTTP/2 server options, introducing an unconstrained attack surface.
At the core of the threat is the HTTP/2 Bomb, also known as the HPACK indexed reference bomb combined with a flow-control window stall. An attacker can exploit this omission by transmitting highly compressed, repetitive HTTP/2 headers that consume disproportionate amounts of server memory. Because the proxy does not limit the maximum size of header lists or the number of concurrent streams, it decompresses these inputs into memory and allocates vast structures for each session.
This vulnerability is classified under CWE-409 (Improper Handling of Highly Compressed Data) and CWE-400 (Uncontrolled Resource Consumption). The real-world consequence is a rapid exhaustion of system memory, leading to out-of-memory (OOM) termination of the proxy process or system-wide resource starvation. This disruption is sustained even after the attack traffic ceases, as the connection state is designed to hold resources open indefinitely.
The technical root cause lies in how the praxis-proxy implementation configures its underlying HTTP/2 session options. The framework relies on a custom fork of Cloudflare's Pingora, which in turn uses the Rust h2 crate for handling low-level HTTP/2 framing. Although Pingora patched this vulnerability in its upstream version v0.8.1, the fork utilized by Praxis lacked these configurations, reverting the HTTP/2 options to their default, unbounded state.
Under default conditions, the h2 crate allows unconstrained header list sizes and does not impose a low threshold on concurrent streams. The HPACK compression scheme defined in RFC 7541 allows client and server to keep a dynamic table of strings. The attacker exploits this by injecting a single, short header into the dynamic table, and subsequently sending thousands of 1-byte indexed references to this empty header. This structure bypasses standard defenses that monitor total decoded header length because the actual decoded string size remains nearly zero.
While the total decoded size of the header strings is minimal, the server must still allocate internal metadata, stream states, and tracking nodes for each individual header entry. The amplification occurs via allocator overhead and metadata replication. To sustain this allocation, the attacker implements a flow-control window stall under RFC 9113, setting the client's receive window to zero. This halts the server from completing the response, pinning all allocated structures in heap memory indefinitely.
Analyzing the vulnerable code path reveals that the HTTP/2 server initialization completely omitted explicit parameters for session constraints. In versions prior to 0.5.2, the praxis_proxy initialization process established standard HTTP/1 server options but did not configure or attach the corresponding H2Options structure to the proxy handler.
// Vulnerable initialization pattern in protocol/src/http/pingora/handler/mod.rs
let mut proxy = http_proxy(&server.configuration, handler);
proxy.server_options = Some(h2c_server_options());
// Missing: proxy.h2_options allocation and configurationThe patch introduced in version 0.5.2 resolves this by explicitly defining and loading a bounded H2Options structure. The function h2_server_options was added to construct the safe boundaries:
/// Build H2Options with limits to mitigate HPACK amplification attacks (CWE-409).
fn h2_server_options() -> H2Options {
let mut opts = H2Options::new();
opts.max_header_list_size(65_536); // Limits decoded header block to 64 KiB
opts.max_concurrent_streams(128); // Limits active streams to 128
opts
}By passing these restricted options to the proxy struct (proxy.h2_options = Some(h2_server_options());), the server enforces strict boundaries. The h2 engine will immediately terminate any session where the incoming header block exceeds 64 KiB, or if a client attempts to open more than 128 concurrent streams on a single TCP connection. This stops the amplification and stalling mechanisms prior to memory allocation.
To successfully execute this exploit, an attacker requires network line-of-sight to the exposed Praxis listener. The attack does not require authentication, making it particularly dangerous. The process begins with establishing a standard TLS connection and negotiating HTTP/2. The attacker then sends a frame containing an HPACK dynamic table update that defines a minimal, space-efficient entry.
Following the table setup, the attacker transmits a series of HEADERS frames populated with thousands of 1-byte references targeting the dynamic table index. Simultaneously, the attacker transmits a SETTINGS frame that modifies the initial window size to zero, or sends flow-control window updates that freeze output processing. The server is forced to parse and track each header reference, allocating memory, but cannot flush or terminate the connection because of the flow control window stall.
In a vulnerability verification setting, running a target Praxis container on version 0.5.1 shows memory usage beginning at approximately 6.47 MiB. Upon executing the HPACK bomb script with just 10 parallel iterations, container memory consumption escalates to over 687.1 MiB in less than five seconds. This memory is not freed after the script disconnects, confirming that the resources remain pinned.
The security impact of GHSA-cjcg-cxmh-9wcr is classified as a High-severity Denial of Service (DoS) vulnerability. Although the exploit does not allow arbitrary code execution, privilege escalation, or unauthorized data retrieval, its ability to completely disable proxy endpoints makes it highly disruptive. The CVSS score of 7.5 reflects this significant threat to system availability.
Because Praxis acts as an entry point for application clusters, a denial of service at this layer propagates downstream, rendering all backend APIs and web services inaccessible to legitimate users. The vulnerability requires minimal attacker sophistication, no prior credentials, and a very low bandwidth footprint, meaning a single attacker can take down large-scale infrastructure using consumer-grade hardware.
Furthermore, the memory amplification is persistent due to the TCP connection-drip mechanism. The server does not release the allocated structures because the streams are considered active under HTTP/2 specifications. This behavior forces system administrators to manually intervene, restart the proxy containers, or rely on aggressive orchestration health checks to recover the service.
The recommended course of action is to immediately upgrade Praxis to version 0.5.2 or higher. This release integrates the upstream Pingora safety configurations, introducing limits on the header size (64 KiB) and concurrent stream capacity (128) which natively neutralizes the HPACK amplification vector. No configuration changes are required when upgrading, as these options are enforced by default.
If immediate software upgrades are not possible, operators should enforce mitigation strategies at other layers of the networking stack. Restricting the maximum memory allowed for the Praxis container via control groups (cgroups) or orchestration configurations (e.g., Kubernetes resource limits) ensures that a resource spike causes a controlled process crash and restart rather than degrading the entire host system.
Additionally, deploying a reverse proxy or a Web Application Firewall (WAF) in front of Praxis that monitors and restricts HTTP/2 settings can block the attack. Detection mechanisms should look for connections characterized by high stream counts, low overall data transfer rates, and the periodic transmission of tiny WINDOW_UPDATE frames. Monitoring tools should alert on rapid memory spikes that correlate with a high rate of uncompleted HTTP/2 connections.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
praxis-proxy praxis-proxy | < 0.5.2 | 0.5.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-409 |
| Attack Vector | Network |
| CVSS Score | 7.5 |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
The product receives highly compressed data and decompresses it or processes indexed compression structures without verifying that the decompressed or processed data does not exceed resource limits.
A Use-After-Free (UAF) vulnerability exists in the sqlite3-ruby native C extension when marshaling arguments for user-defined SQLite aggregate functions with multiple arguments. Due to temporary heap-allocated argument arrays not being registered with the Ruby Garbage Collector, active objects can be prematurely reclaimed, resulting in memory corruption or process-level crashes.
An unauthenticated remote denial of service vulnerability exists in @fastify/busboy versions 3.1.0 through 3.2.0. The vulnerability is caused by an integer wrap-around in the Boyer-Moore-Horspool algorithm implementation inside the sbmh submodule when initializing skip distances. When processing a specific boundary of 252 bytes, the parser triggers an infinite loop, stalling the single-threaded Node.js event loop and exhausting CPU resources.
A critical remote, unauthenticated Denial of Service (DoS) vulnerability in @fastify/busboy (<= 3.2.0) allows attackers to crash the Node.js process. By submitting a crafted multipart/form-data request with a header key matching an inherited property of Object.prototype (like __proto__ or constructor), the internal HeaderParser triggers a synchronous TypeError.
SiYuan is an open-source personal knowledge management system. Its Model Context Protocol (MCP) implementation within the asset.upload tool contains a path-traversal and workspace boundary bypass flaw. This allows remote AI models—acting on behalf of attackers via malicious prompts or documents—to import and read sensitive host-system files, such as private keys and system configurations, through absolute path inputs.
An Server-Side Request Forgery (SSRF) vulnerability via DNS-Rebinding Time-of-Check to Time-of-Use (TOCTOU) has been discovered in SiYuan (思源笔记), an open-source personal knowledge management system. The flaw exists within the AI Agent tools http_request (util.HTTPRequest) and web_fetch (util.WebFetch) of the SiYuan Kernel, allowing unauthenticated remote attackers to bypass SSRF validation and access private internal services or cloud metadata endpoints.
An uncontrolled resource consumption vulnerability (CWE-1333 / CWE-400) exists in probe-image-size versions prior to 7.4.0. The SVG parser utilizes an unanchored, inefficient regular expression to find the SVG root tag, leading to catastrophic backtracking when handling malformed payloads. This blocks the single-threaded Node.js event loop, resulting in a complete denial of service.