GHSA-vpp8-g58w-m8mp: Twisted: Unauthenticated Remote Denial of Service in the Twisted HTTP/2 Server via Rapid Stream Reset

Published Oct 29, 2026
·
Updated

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 ENDSTREAM 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(ENDSTREAM) followed by RSTSTREAM 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 ENDSTREAM on a fresh stream identifier immediately followed by a RSTSTREAM 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.

Affected Software

2 affected componentsFixes available
pip/twisted<=26.4.0
26.10.0rc1
pip/twisted<26.10.0rc1
26.10.0rc1

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/Twisted to a version that resolves this vulnerability.

    Fixed in 26.10.0rc1
  2. Upgrade

    Upgrade pip/twisted to a version that resolves this vulnerability.

    Fixed in 26.10.0rc1

Event History

Oct 29, 2026
Advisory Published
via GitHub·04:41 PM
Data Sourced
via GitHub·04:41 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are exposed?

Deployments using the Twisted HTTP/2 server are exposed. The issue is specific to HTTP/2 request handling.

2

What does an attacker need to exploit this?

An attacker only needs network access to the HTTP/2 server. No authentication, user interaction, or multiple connections are required; the attack can be repeated at line rate over a single connection.

3

Why do normal HTTP/2 stream limits not prevent this attack?

The malicious streams are reset after sending an end-of-stream header block. Twisted dispatches and synchronously renders the request before processing the reset, while reset streams are freed and do not count against the concurrent-stream limit; no reset-rate limiter is present.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203