GHSA-CJCG-CXMH-9WCR

Vulnerability from github – Published: 2026-10-02 23:09 – Updated: 2026-10-02 23:09
VLAI
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
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "praxis-proxy"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.5.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-409"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-02T23:09:37Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "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\u0027m 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.\u00a0(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(\u0026server.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(\u0026mut 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```",
  "id": "GHSA-cjcg-cxmh-9wcr",
  "modified": "2026-10-02T23:09:37Z",
  "published": "2026-10-02T23:09:37Z",
  "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"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Praxis affected by HTTP/2 Bomb "
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.