GHSA-cjcg-cxmh-9wcr: Praxis proxy Praxis Affected By HTTP/2 Bomb Vulnerability

HIGH
CVSS 7.5
CWE-409
Published
Advisory Summary

GHSA-cjcg-cxmh-9wcr is a HIGH (CVSS 7.5) praxis affected by http/2 bomb vulnerability (CWE-409: Improper Handling of Highly Compressed Data (Data Amplification)) affecting Praxis proxy libraries in the crates.io ecosystem. The issue involves praxis affected by http/2 bomb. Remediation is available by upgrading affected packages to version 0.5.2.

GHSA-cjcg-cxmh-9wcr at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-cjcg-cxmh-9wcr
Severity HIGH
CVSS v3.1 Base Score 7.5
CWE Classification CWE-409: Improper Handling of Highly Compressed Data (Data Amplification)
Affected Product Praxis proxy
Package Ecosystem crates.io
Published Date
Last Updated

Security Impact

CVSS: 7.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required None (PR:N)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity None (I:N)
Availability High (A:H)

How to Fix GHSA-cjcg-cxmh-9wcr

To remediate this vulnerability, upgrade all affected Praxis proxy dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

praxis-proxy fixed: 0.5.2
Upgrade praxis-proxy to 0.5.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for praxis-proxy

How to Check if You Are Affected

To determine whether your application is affected by GHSA-cjcg-cxmh-9wcr, inspect your project dependencies for Praxis proxy:

inspect dependencies for praxis-proxy

Analyze the terminal output to locate any version of Praxis proxy in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.5.2), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification), where the product does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output. In Praxis proxy, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Multiple 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. ### 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): 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](https://github.com/praxis-proxy/pingora/commit/d193c8d49b8b7c1c1ede93183759caa4f6906bbd) 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 ```

GHSA-cjcg-cxmh-9wcr Affected Praxis proxy Versions

1 component(s)
Fixed Versions:
0.5.2
Product / Package Ecosystem Affected Versions Fixed Version
praxis-proxy
crates.io
< 0.5.2
0.5.2

References

Frequently Asked Questions

What is GHSA-cjcg-cxmh-9wcr?
GHSA-cjcg-cxmh-9wcr is a security vulnerability in Praxis proxy involving Praxis affected by HTTP/2 Bomb under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification).
Which Praxis proxy versions are affected?
Affected versions include releases prior to 0.5.2 across affected packages: praxis-proxy.
What version fixes GHSA-cjcg-cxmh-9wcr?
Upgrading to 0.5.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is praxis-proxy affected?
Yes, praxis-proxy is affected in releases prior to 0.5.2. Upgrade your dependency to 0.5.2 or later.
What is the CVSS score of GHSA-cjcg-cxmh-9wcr?
GHSA-cjcg-cxmh-9wcr has a CVSS v3.1 base score of 7.5 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H.
What CWE is associated with GHSA-cjcg-cxmh-9wcr?
GHSA-cjcg-cxmh-9wcr is classified under CWE-409: Improper Handling of Highly Compressed Data (Data Amplification) (The product does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output.).
How can I check crates.io dependencies for GHSA-cjcg-cxmh-9wcr?
Run the dependency tree command: 'inspect dependencies for praxis-proxy'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-cjcg-cxmh-9wcr",
  "modified" : "2026-10-02T23:09:37Z",
  "published" : "2026-10-02T23:09:37Z",
  "aliases" : [ ],
  "summary" : "Praxis affected by HTTP/2 Bomb ",
  "details" : "### 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```",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "crates.io",
      "name" : "praxis-proxy"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.5.2"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/praxis-proxy/praxis/security/advisories/GHSA-cjcg-cxmh-9wcr"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/praxis-proxy/praxis/commit/2bb7b29d6992fc2d8045628475912d734e6bee97"
  }, {
    "type" : "WEB",
    "url" : "https://access.redhat.com/security/vulnerabilities/RHSB-2026-007"
  }, {
    "type" : "WEB",
    "url" : "https://blog.calif.io/p/codex-discovered-a-hidden-http2-bomb"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/praxis-proxy/praxis"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/praxis-proxy/praxis/releases/tag/v0.5.2"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-409" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-10-02T23:09:37Z",
    "nvd_published_at" : null
  }
}