Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 274/275 feeds/APIs · 469/469 docs · 7/9 advisories · checked 19:00 UTC Customize Public modeDiscuss ChangeIntel on Discord

Praxis affected by HTTP/2 Bomb

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

osv · GHSA-cjcg-cxmh-9wcr

Published

### 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 ```

Source published
2 Oct 2026 23:09:37 UTC
Source modified
2 Oct 2026 23:30:06 UTC
Observed here
24 Oct 2026 13:19:54 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Publisher rating · HIGH

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 11 Nov 19:00 UTC · 274 of 275 readable · 273 fully read · documentation 469/469 current