GitHub Advisoryadvisory · crates.io

GHSA-cjcg-cxmh-9wcr Praxis affected by HTTP/2 Bomb

HIGH Published 2026-10-02 Modified 2026-10-02 Official page ↗
Ecosystem
crates.io
Packages
praxis-proxy
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-409
Reviewed
2026-10-02

Affected packages

• crates.io praxis-proxy: < 0.5.2 → fixed in 0.5.2

Description

Summary Multiple denial-of-service vulnerabilities have been discovered in HTTP/2 server implementations. All have been rated with a severity impact of Important. The vulnerabilities target HPACK, the header compression scheme in HTTP/2, where a small request can trigger large memory allocations on the server. Details Credit to the original researcher, I'm mostly just run their tool against the code base. Security Bulletins: https://access.redhat.com/security/vulnerabilities/RHSB-2026-007 Exploit details: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb This bug was fixed in upstream pingora v0.8.1, but our fork (v0.8.2) is missing this important PR to set the default h2 options. (edited) PoC • Generate certificates ``` openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout server.key -out server.crt -days 3650 -nodes -subj "/CN=localhost" ``` • Create praxis config as follow ``` listeners: • name: web address: "0.0.0.0:8443" tls: certificates: • cert_path: /etc/praxis/server.crt key_path: /etc/praxis/server.key filter_chains: [main] filter_chains: • name: main filters: • filter: router routes: • path_prefix: "/" host: "example.api.com" cluster: backend • filter: load_balancer clusters: • name: backend endpoints: • "httpbingo.org:443" tls: verify: false ``` • Start the container ``` docker run --name praxis --user $(id -u):$(id -g) -it --rm -p 8443:8443 -v ./config.yaml:/etc/praxis/config.yaml -v ./server.crt:/etc/praxis/server.crt -v ./server.key:/etc/praxis/server.key ghcr.io/praxis-proxy/praxis:0.5.1 ``` • Check container memory ``` $ docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 362cfa472792 praxis 0.00% 6.473MiB / 62.49GiB 0.01% 7.57kB / 126B 0B / 0B 22 ``` • In another terminal run the attack ``` ./hpack_bomb.py --host 127.0.0.1 --port 8443 -n 10 ``` • Observer the container memory ``` 98b040c5e5ad praxis 0.13% 687.1MiB / 62.49GiB 1.07% 41.6MB / 362kB 0B / 0B 23 ``` Memory usage spiked to around 700MB, and even after the attack ended, the memory was not freed up. • Patch the code to set h2options ``` diff --git a/protocol/src/http/pingora/handler/mod.rs b/protocol/src/http/pingora/handler/mod.rs index dc684ad..fc59234 100644 --- a/protocol/src/http/pingora/handler/mod.rs +++ b/protocol/src/http/pingora/handler/mod.rs @@ -18,6 +18,7 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; use arc_swap::ArcSwap; use bytes::Bytes; +use pingora_core::protocols::http::v2::server::H2Options; use pingora_core::{Result, apps::HttpServerOptions, server::Server, services::listening::Service}; use pingora_proxy::{Session, http_proxy}; use praxis_core::{config::ABSOLUTE_MAX_BODY_BYTES, connectivity::Upstream}; @@ -151,6 +152,11 @@ where let service_name = format!("http-proxy:{name}", name = listener.name); let mut proxy = http_proxy(&server.configuration, handler); proxy.server_options = Some(h2c_server_options()); + let mut h2_options = H2Options::new(); + h2_options.max_header_list_size(65536); + h2_options.max_concurrent_streams(32); + proxy.h2_options = Some(h2_options); + let mut service = Service::new(service_name, proxy); if let Some(tx) = super::listener::add_listener(&mut service, listener)? { cert_watcher_shutdowns.push(tx); ``` • Rerun the attack, the memory usage looks a lot better now ``` CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS b1c82abca409 praxis 0.04% 10.09MiB / 62.49GiB 0.02% 1.16MB / 23.4kB 950kB / 0B 23 ```

Related

Weakness · CWE (1)

  • CWE-409 Improper Handling of Highly Compressed Data (Data Amplification) weakness

References