Rapid stream reset in Twisted HTTP/2 server causes denial of service
Key facts
- Attack vector
- —
- Privileges required
- —
- User interaction
- —
- Attack complexity
- —
- Impact type
- Denial of service
- Confidentiality · integrity · availability
- —
- Fix status
- Fixed
No CVSS vector from any source. Fix status from GitHub. Impact type from CWE-400.
Summary
Twisted's twisted.web HTTP/2 server is affected from 0 before 26.10.0rc1. The server processes a request on stream end before handling a reset that follows it, and freed reset streams are never counted or throttled, so a remote client without credentials can repeat this pattern on one connection (CWE-400). Sustained traffic exhausts server CPU, causing denial of service.
Written with Claude Haiku 5.5 from the sources below · 2026-10-29
Description from the GitHub advisory
## Summary An uncontrolled-resource-consumption vulnerability (CWE-400) in the Twisted HTTP/2 server lets any unauthenticated remote client exhaust server CPU over a single connection. A client that sends a request header block with `END_STREAM` and then immediately resets the stream makes the server route and render the request before it processes the reset. Reset streams are freed and never count against the concurrent-stream limit, and no reset-rate limiter exists, so the pattern can be repeated at line rate on one connection. This is the HTTP/2 Rapid Reset class, CVE-2023-44487. ## Details For one received segment the h2 events are processed in order in `H2Connection.dataReceived`. A `HEADERS(END_STREAM)` followed by `RST_STREAM` yields `RequestReceived`, `StreamEnded`, then `StreamReset`, so the request is dispatched and rendered on stream end before the reset is handled: ```python # src/twisted/web/_http2.py (H2Connection.dataReceived) for event in events: if isinstance(event, h2.events.RequestReceived): self._requestReceived(event) # allocate the request elif isinstance(event, h2.events.StreamEnded): self._requestEnded(event) # -> requestComplete -> render() synchronously elif isinstance(event, h2.events.StreamReset): self._requestAborted(event) # processed last, frees the stream ``` `_requestAborted` frees the reset stream, so it never occupies the 100-stream concurrency budget, and nothing in `_http2.py` counts or throttles opened-and-reset streams. The 2019 flood fix (GHSA-32gv) bounds outbound control-frame buffering only and does not apply to this path. Affected product: Twisted, `twisted.web` HTTP/2 server Affected versions: confirmed against 26.4.0 ## PoC On any Twisted HTTP/2 endpoint, open one connection and, in a tight loop, send a `HEADERS` frame with `END_STREAM` on a fresh stream identifier immediately followed by a `RST_STREAM` for that stream, at line rate. No credentials are required. The server renders each request on stream end before the reset frees the stream, and a freed stream never counts toward the concurrent-stream limit, so the loop is never throttled. Because every cancelled stream is still dispatched in full and reset streams do not accumulate, the connection is never throttled or closed, so the forced work grows with the number of pairs sent. Sustained on one connection this saturates a CPU core under only a trickle of traffic, whereas a client that instead leaves its streams open is closed once it reaches the concurrent-stream limit. ## Impact This is an unauthenticated remote denial of service (CWE-400, CWE-770) by CPU exhaustion. One connection forces unbounded request rendering at a few frames per cancelled request, bypassing the concurrent-stream limit. It is the HTTP/2 Rapid Reset class (CVE-2023-44487), not covered by the earlier Twisted flood fix, with no confidentiality or integrity impact and no code execution.
Why it matters now
SSVC decision points
Not available: CISA has not published SSVC decision points for this record.
Affected products
| Vendor | Product | Affected versions | Fixed in | Status | Source |
|---|---|---|---|---|---|
| — | Twisted (PyPI) | before 26.10.0rc1 | 26.10.0rc1 | Patch available | GHSA-vpp8-g58w-m8mp |
- Twisted (PyPI) Vendor— Affected before 26.10.0rc1 Fixed in 26.10.0rc1 Patch available GHSA-vpp8-g58w-m8mp
Remediation
Upgrade Twisted to 26.10.0rc1 or later.
Written with Claude Haiku 5.5 from the sources below · 2026-10-29
- Fix · GHSA-vpp8-g58w-m8mp Twisted (PyPI) Fixed in 26.10.0rc1 Advisory →
Timeline
- 2026-10-29 Threatist record created from GHSA-vpp8-g58w-m8mp
References
Other 5
- https://github.com/twisted/twisted/security/advisories/GHSA-vpp8-g58w-m8mp
- https://github.com/twisted/twisted/pull/12749
- https://github.com/twisted/twisted/commit/498939422b69d5a75c4b8f81fa7926423dac534d
- https://github.com/twisted/twisted
- https://github.com/twisted/twisted/releases/tag/twisted-26.10.0rc1
Sources
This product uses the NVD API but is not endorsed or certified by the NVD. Sources and licences