GHSA-cjcg-cxmh-9wcr

Suggest an improvement
Source
https://github.com/advisories/GHSA-cjcg-cxmh-9wcr
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-cjcg-cxmh-9wcr/GHSA-cjcg-cxmh-9wcr.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-cjcg-cxmh-9wcr
Published
2026-10-02T23:09:37Z
Modified
2026-10-02T23:30:06Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVSS Calculator
Summary
Praxis affected by HTTP/2 Bomb
Details

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
Database specific
{
    "cwe_ids":  [
        "CWE-409"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-10-02T23:09:37Z",
    "nvd_published_at":  null,
    "severity":  "HIGH"
}
References

Affected packages

crates.io / praxis-proxy

Package

Name
praxis-proxy
View open source insights on deps.dev
Purl
pkg:cargo/praxis-proxy

Affected ranges

Type
SEMVER
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
0.5.2

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-cjcg-cxmh-9wcr/GHSA-cjcg-cxmh-9wcr.json"