Tomcat HTTP/2 resource-exhaustion boundary batch¶
Source: GitHub Security Advisories REST fallback, updated 2026-05-20.
This batch is durable because both advisories describe HTTP/2 protocol handling that lets a remote client convert small connection or stream choices into process-wide Tomcat memory or thread exhaustion. The affected releases are old, but the defensive lesson remains current for any Java edge service that terminates h2c/HTTP/2 directly.
What changed¶
- Tomcat h2c upgrade processor leak leading to OOM — GHSA-vf77-8h7g-gghp / CVE-2020-13934: Tomcat
10.0.0-M1through10.0.0-M5,9.0.0.M5before9.0.36, and8.5.1before8.5.56failed to release the HTTP/1.1 processor after an h2c upgrade to HTTP/2. Enough direct h2c upgrade requests could triggerOutOfMemoryExceptionand deny service. - Tomcat HTTP/2 SETTINGS and blocking-I/O stream exhaustion — GHSA-qcxh-w3j9-58qr / CVE-2019-0199: Tomcat
9.0.0.M1through9.0.14and8.5.0through8.5.37accepted excessive HTTP/2 SETTINGS frames and allowed streams to stay open without request/response progress. When those streams used Servlet API blocking I/O, attacker-held streams could exhaust server threads.
Operator triage¶
- Confirm every internet-facing or proxy-facing Tomcat runtime is newer than
9.0.36or8.5.56; for embeddedtomcat-embed-core, require at least9.0.16or8.5.38for the older SETTINGS/thread exhaustion issue and newer patched lines for the h2c leak. - Inventory whether h2c direct upgrade is enabled anywhere. If HTTP/2 is required, prefer terminating it at a hardened reverse proxy and forwarding bounded HTTP/1.1 or a separately monitored backend protocol.
- Review access logs and reverse-proxy metrics for repeated h2c upgrades, high HTTP/2 SETTINGS frame rates, many idle streams per client, or servlet threads stuck in blocking I/O.
- For legacy apps that cannot move immediately, restrict HTTP/2/h2c exposure to trusted frontends, cap concurrent streams, enforce idle/read/write timeouts, and add memory/thread-pool saturation alerts.
Replayable validation boundaries¶
- h2c upgrade lifecycle test: send repeated HTTP/1.1-to-h2c upgrade requests against a staging Tomcat; expected result is stable processor counts and heap use after connection close.
- SETTINGS flood test: generate HTTP/2 streams with excessive SETTINGS frames through the approved edge path; expected result is rate limiting, connection closure, or proxy rejection before Tomcat worker/thread exhaustion.
- Idle blocking stream test: hold request/response streams open against a blocking servlet endpoint; expected result is bounded per-client streams and timeout-driven cleanup.
- Proxy containment test: attempt direct h2c access to the Tomcat backend from untrusted networks; expected result is no route or explicit rejection.
Durable controls¶
- Treat HTTP/2 and h2c as resource-boundary surfaces, not just transport features. Every enabled connector needs stream, frame, timeout, thread, and heap budgets.
- Keep Tomcat and embedded Tomcat dependencies patched even for internal services; old h2c/HTTP/2 flaws are easy to rediscover with generic protocol fuzzers.
- Terminate complex client protocols at one hardened, observable edge layer whenever possible, and keep backend connectors private.
- Monitor connector-level counters: active HTTP/2 streams, refused streams, idle stream age, servlet thread utilization, direct-buffer/heap pressure, and h2c upgrade rates.
- Include HTTP/2 slow-read, SETTINGS-frame, and h2c-upgrade regressions in load and abuse tests for Java services.