{"id":"GHSA-cjcg-cxmh-9wcr","title":"Praxis affected by HTTP/2 Bomb ","summary":"Praxis affected by HTTP/2 Bomb ","severity":"high","cvss":7.5,"cwe":["CWE-409"],"vendor":"praxis-proxy","product":"praxis-proxy","ecosystem":"rust","affected":["praxis-proxy < 0.5.2"],"patched":["praxis-proxy 0.5.2"],"published":"2026-10-02","updated":"2026-10-02","sourceUpdated":"2026-10-02T23:09:38Z","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-cjcg-cxmh-9wcr","references":[{"url":"https://github.com/praxis-proxy/praxis/security/advisories/GHSA-cjcg-cxmh-9wcr"},{"url":"https://github.com/praxis-proxy/praxis/commit/2bb7b29d6992fc2d8045628475912d734e6bee97"},{"url":"https://access.redhat.com/security/vulnerabilities/RHSB-2026-007"},{"url":"https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb"},{"url":"https://github.com/praxis-proxy/praxis/releases/tag/v0.5.2"},{"url":"https://github.com/advisories/GHSA-cjcg-cxmh-9wcr"}],"tags":["ghsa","rust"],"ingestedAt":"2026-10-02T23:34:57.395Z","slug":"GHSA-cjcg-cxmh-9wcr","body":"## Overview\n\n### Summary\n\nMultiple denial-of-service vulnerabilities have been discovered in HTTP/2 server implementations. All have been rated with a severity impact of [Important](https://access.redhat.com/security/updates/classification). The vulnerabilities target HPACK, the header compression scheme in HTTP/2, where a small request can trigger large memory allocations on the server. \n\n### Details\n\nCredit to the original researcher, I'm mostly just run their tool against the code base.\n\n[Security Bulletins](https://access.redhat.com/security/vulnerabilities/RHSB-2026-007): https://access.redhat.com/security/vulnerabilities/RHSB-2026-007 \nExploit details: https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb\n\nThis bug was fixed in upstream pingora v0.8.1, but our fork (v0.8.2) is missing this important [PR](https://github.com/praxis-proxy/pingora/commit/d193c8d49b8b7c1c1ede93183759caa4f6906bbd) to set the default h2 options. (edited)\n\n### PoC\n\n* Generate certificates\n```\nopenssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout server.key -out server.crt -days 3650 -nodes -subj \"/CN=localhost\"\n```\n\n* Create praxis config as follow\n\n```\nlisteners:\n  - name: web\n    address: \"0.0.0.0:8443\"\n    tls:\n      certificates:\n        - cert_path: /etc/praxis/server.crt\n          key_path: /etc/praxis/server.key\n    filter_chains: [main]\n\nfilter_chains:\n  - name: main\n    filters:\n      - filter: router\n        routes:\n          - path_prefix: \"/\"\n            host: \"example.api.com\"\n            cluster: backend\n      - filter: load_balancer\n        clusters:\n          - name: backend\n            endpoints:\n              - \"httpbingo.org:443\"\n            tls:\n                verify: false\n```\n\n* Start the container\n\n```\ndocker 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\n```\n\n* Check container memory\n\n```\n$ docker stats\n\nCONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT     MEM %     NET I/O         BLOCK I/O        PIDS\n362cfa472792   praxis          0.00%     6.473MiB / 62.49GiB   0.01%     7.57kB / 126B   0B / 0B          22\n```\n\n* In another terminal run the attack\n\n```\n./hpack_bomb.py --host 127.0.0.1 --port 8443 -n 10\n```\n\n* Observer the container memory\n\n```\n98b040c5e5ad   praxis          0.13%     687.1MiB / 62.49GiB   1.07%     41.6MB / 362kB   0B / 0B          23\n```\n\nMemory usage spiked to around 700MB, and even after the attack ended, the memory was not freed up.\n* Patch the code to set h2options\n\n```\ndiff --git a/protocol/src/http/pingora/handler/mod.rs b/protocol/src/http/pingora/handler/mod.rs\nindex dc684ad..fc59234 100644\n--- a/protocol/src/http/pingora/handler/mod.rs\n+++ b/protocol/src/http/pingora/handler/mod.rs\n@@ -18,6 +18,7 @@ use std::{collections::HashMap, sync::Arc, time::Duration};\n\n use arc_swap::ArcSwap;\n use bytes::Bytes;\n+use pingora_core::protocols::http::v2::server::H2Options;\n use pingora_core::{Result, apps::HttpServerOptions, server::Server, services::listening::Service};\n use pingora_proxy::{Session, http_proxy};\n use praxis_core::{config::ABSOLUTE_MAX_BODY_BYTES, connectivity::Upstream};\n@@ -151,6 +152,11 @@ where\n     let service_name = format!(\"http-proxy:{name}\", name = listener.name);\n     let mut proxy = http_proxy(&server.configuration, handler);\n     proxy.server_options = Some(h2c_server_options());\n+    let mut h2_options = H2Options::new();\n+    h2_options.max_header_list_size(65536);\n+    h2_options.max_concurrent_streams(32);\n+    proxy.h2_options = Some(h2_options);\n+\n     let mut service = Service::new(service_name, proxy);\n     if let Some(tx) = super::listener::add_listener(&mut service, listener)? {\n         cert_watcher_shutdowns.push(tx);\n```\n\n* Rerun the attack, the memory usage looks a lot better now\n\n```\nCONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O    PIDS\nb1c82abca409   praxis    0.04%     10.09MiB / 62.49GiB   0.02%     1.16MB / 23.4kB   950kB / 0B   23\n```\n\n## Affected packages\n\n- `praxis-proxy < 0.5.2`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `praxis-proxy 0.5.2`","depth":"twilight","depthScore":41,"depthScoreParts":{"impact":41.3,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}