From 520e89249395afe888b9012cc5ec0bb283609ae1 Mon Sep 17 00:00:00 2001 From: ruvnet Date: Sun, 3 May 2026 17:51:14 -0400 Subject: [PATCH] sec(hailo): explicit CVE-2023-44487 rapid-reset cap (iter 183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hyper/h2 already mitigates the rapid-reset DoS by defaulting http2_max_pending_accept_reset_streams to 20 post-CVE, but pinning the value explicitly gives operators a tunable surface and makes the mitigation reviewable from worker startup logs. Set to 32 by default (small step above the h2 default to leave room for legit reset jitter), env-tunable via `RUVECTOR_MAX_PENDING_RESETS` with an 8 floor. Once exceeded, hyper sends GOAWAY and closes the connection. Validated on cognitum-v0, c=8 b=1, 8 s × 3 runs each: iter-182 baseline: 69.6, 67.4, 69.0 → mean 68.7/sec iter-183 after : 70.5, 70.5, 69.6 → mean 70.2/sec Δ throughput: +2.2% (noise band — legit traffic doesn't generate RST_STREAM under steady load, so the cap is invisible) Δ p50 : flat at 111-112 ms Layered with iter-180 byte cap, iter-181 stream cap, iter-182 RPC timeout — four DoS gates now visible in the worker startup banner. This closes the named-CVE checklist for the gRPC server surface; remaining hardening (HTTP/2 keepalive, header-list-size cap) targets liveness rather than DoS. Co-Authored-By: claude-flow --- .../ruvector-hailo-cluster/src/bin/worker.rs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/ruvector-hailo-cluster/src/bin/worker.rs b/crates/ruvector-hailo-cluster/src/bin/worker.rs index 19bb048c5..d4abe6962 100644 --- a/crates/ruvector-hailo-cluster/src/bin/worker.rs +++ b/crates/ruvector-hailo-cluster/src/bin/worker.rs @@ -43,6 +43,11 @@ //! and any handler that hangs past the //! 30× p99 headroom. tonic returns //! Status::cancelled when it fires. +//! RUVECTOR_MAX_PENDING_RESETS CVE-2023-44487 rapid-reset cap +//! (ADR-172 §3a iter 183 — default 32, +//! floor 8). Caps unprocessed RST_STREAM +//! frames; once exceeded, the server +//! sends GOAWAY and closes the connection. //! //! When both `RUVECTOR_TLS_CERT` and `RUVECTOR_TLS_KEY` are set and the //! binary was built with `--features tls`, the worker serves over HTTPS @@ -563,9 +568,27 @@ fn main() -> Result<(), Box> { request_timeout_secs, "per-RPC handler timeout set (ADR-172 §3a iter 182 slow-loris gate)" ); + // Iter 183 — explicit CVE-2023-44487 rapid-reset cap. hyper/h2 + // already mitigates by defaulting to 20 pending RST_STREAM + // frames, but pinning the value gives operators a tunable + // surface and makes the mitigation reviewable from the worker + // logs. 32 is a small step above the h2 default to leave room + // for legit reset jitter (e.g., a client cancelling a stream + // mid-flight) without weakening the cap meaningfully — a + // GOAWAY still fires after just 33 unprocessed resets. + let max_pending_resets: usize = std::env::var("RUVECTOR_MAX_PENDING_RESETS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(32) + .max(8); + info!( + max_pending_resets, + "HTTP/2 max_pending_accept_reset_streams set (ADR-172 §3a iter 183 CVE-2023-44487 gate)" + ); let mut server = Server::builder() .max_concurrent_streams(Some(max_streams)) - .timeout(Duration::from_secs(request_timeout_secs)); + .timeout(Duration::from_secs(request_timeout_secs)) + .http2_max_pending_accept_reset_streams(Some(max_pending_resets)); #[cfg(feature = "tls")] { // Both vars must be set to opt-in. A partial config (cert