GHSA-vpp8-g58w-m8mp

Suggest an improvement
Source
https://github.com/advisories/GHSA-vpp8-g58w-m8mp
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-vpp8-g58w-m8mp/GHSA-vpp8-g58w-m8mp.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-vpp8-g58w-m8mp
Published
2026-10-29T16:41:06Z
Modified
2026-10-29T17:00:04Z
Severity
  • 7.5 (High) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H CVSS Calculator
Summary
Twisted: Unauthenticated Remote Denial of Service in the Twisted HTTP/2 Server via Rapid Stream Reset
Details

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:

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

Database specific
{
    "cwe_ids":  [
        "CWE-400",
        "CWE-770"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-10-29T16:41:06Z",
    "nvd_published_at":  null,
    "severity":  "HIGH"
}
References

Affected packages

PyPI / twisted

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
26.10.0rc1

Affected versions

1.*
1.0.1
1.0.3
1.0.4
1.0.5
1.0.6
1.0.7
1.1.0
1.1.1
1.2.0
2.*
2.1.0
2.4.0
2.5.0
8.*
8.0.0
8.0.1
8.1.0
8.2.0
9.*
9.0.0
10.*
10.0.0
10.1.0
10.2.0
11.*
11.0.0
11.1.0
12.*
12.0.0
12.1.0
12.2.0
12.3.0
13.*
13.0.0
13.1.0
13.2.0
14.*
14.0.0
14.0.1
14.0.2
15.*
15.0.0
15.1.0
15.2.0
15.2.1
15.3.0
15.4.0
15.5.0
16.*
16.0.0
16.1.0
16.1.1
16.2.0
16.3.0
16.3.1
16.3.2
16.4.0
16.4.1
16.5.0rc1
16.5.0rc2
16.5.0
16.6.0rc1
16.6.0
16.7.0rc1
16.7.0rc2
17.*
17.1.0rc1
17.1.0
17.5.0
17.9.0rc1
17.9.0
18.*
18.4.0rc1
18.4.0
18.7.0rc1
18.7.0rc2
18.7.0
18.9.0rc1
18.9.0
19.*
19.2.0rc1
19.2.0rc2
19.2.0
19.2.1
19.7.0rc1
19.7.0
19.10.0rc1
19.10.0
20.*
20.3.0rc1
20.3.0
21.*
21.2.0rc1
21.2.0
21.7.0rc1
21.7.0rc2
21.7.0rc3
21.7.0
22.*
22.1.0rc1
22.1.0
22.2.0rc1
22.2.0
22.4.0rc1
22.4.0
22.8.0rc1
22.8.0
22.10.0rc1
22.10.0
23.*
23.8.0rc1
23.8.0
23.10.0rc1
23.10.0
24.*
24.2.0rc1
24.3.0
24.7.0rc1
24.7.0rc2
24.7.0
24.10.0rc1
24.10.0
24.11.0rc1
24.11.0rc2
24.11.0
25.*
25.5.0rc1
25.5.0
26.*
26.4.0rc2
26.4.0

Database specific

last_known_affected_version_range
"<= 26.4.0"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-vpp8-g58w-m8mp/GHSA-vpp8-g58w-m8mp.json"