Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
MEDIUM severity

Autobahn Python: permessage-brotli inflates a whole frame before maxMessagePayloadSize is checked (incomplete fix of GHSA-hxp9-w8x3-p566)GHSA-pjh6-c8mg-3x7m

MEDIUMFix: crossbario/autobahn-python#1987

GHSA-pjh6-c8mg-3x7m is a medium-severity (CVSS 5.9) CWE-409 vulnerability in autobahn. A fix is available for autobahn — see the affected versions and patch details below.

Also known asCVE-2026-116579
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 28, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for GHSA-pjh6-c8mg-3x7m.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs37th percentile — riskier than 37% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

GHSA-pjh6-c8mg-3x7m by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 396,966 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍autobahn

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

permessage-brotli inflates each frame fully before checking maxMessagePayloadSize, so one 421-byte frame makes the server allocate about 545 MiB even with a 1 MiB message limit (brotli expands about 1,000,000:1). Any unauthenticated client can exhaust server memory this way on servers that enable permessage-brotli. This bypasses the GHSA-hxp9-w8x3-p566 fix.

Details

In 26.7.1 the receive path passes the remaining maxMessagePayloadSize budget to decompress_message_data(..., max_output_len=...). deflate and bzip2 stop at that budget. PerMessageBrotli.decompress_message_data (compress_brotli.py) instead calls self._decompressor.process(data) with no limit and compares the length afterwards, so the whole frame is inflated first.

The code comment and changelog say this is still "bounded on the wire by maxFramePayloadSize", but brotli reaches about 1,000,000:1 (841 bytes inflate to 1 GiB), so that bound means little. A 421-byte frame against a 1 MiB budget peaks at 545 MiB before the 1009 rejection.

An autobahn asyncio server on 127.0.0.1 accepting permessage-brotli, with maxFramePayloadSize=64 KiB and maxMessagePayloadSize=1 MiB, received one small brotli frame from an autobahn client and peaked at 545 MiB (baseline 28 MiB). A few concurrent connections can exhaust memory.

brotli ≥ 1.2.0 has Decompressor.process(data, output_buffer_limit=N), so the backend can stop at max_output_len like deflate and bzip2 (and the extra's floor can be raised to brotli>=1.2.0).

Tested on autobahn 26.7.1 (latest) with brotli 1.2.0; compress_brotli.py on master is unchanged. This affects servers that enable permessage-brotli (opt-in, needs the compress extra).

Proof of concept

How to run the PoC

python3 -m venv venv && . venv/bin/activate
pip install autobahn==26.7.1 brotli==1.2.0
python3 poc_autobahn.py
# PoC: autobahn 26.7.1 permessage-brotli inflates a whole frame before maxMessagePayloadSize is checked.
import brotli, resource
from autobahn.websocket.compress import PerMessageBrotli

c = brotli.Compressor()  # build a 256 MiB-of-zeros frame without holding the plaintext
frame = b"".join(c.process(b"\0" * (1 << 20)) for _ in range(256)) + c.finish()
pmce = PerMessageBrotli(is_server=True, server_no_context_takeover=False, client_no_context_takeover=False)
pmce.start_decompress_message()
print(len(frame), "bytes on the wire; peak RSS before:", resource.getrusage(resource.RUSAGE_SELF).ru_maxrss >> 10, "MiB")
try:
    pmce.decompress_message_data(frame, max_output_len=1 << 20)  # remaining budget: 1 MiB
except Exception as e:
    print(type(e).__name__, "| peak RSS after:", resource.getrusage(resource.RUSAGE_SELF).ru_maxrss >> 10, "MiB")

Output:

421 bytes on the wire; peak RSS before: 36 MiB
PayloadExceededError | peak RSS after: 545 MiB

Impact

An unauthenticated WebSocket client can make a server that enabled permessage-brotli allocate hundreds of MB or more per tiny frame, regardless of the configured maxMessagePayloadSize. That is the memory-exhaustion DoS GHSA-hxp9-w8x3-p566 was meant to prevent.

Credit goes to Adrian Korwel.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIautobahn≥ 26.7.1&&< 26.10.126.10.1pip install --upgrade 'autobahn==26.10.1'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for autobahn, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update autobahn to 26.10.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-pjh6-c8mg-3x7m is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Frequently Asked Questions

### Summary permessage-brotli inflates each frame fully before checking maxMessagePayloadSize, so one 421-byte frame makes the server allocate about 545 MiB even with a 1 MiB message limit (brotli expands about 1,000,000:1). Any unauthenticated client can exhaust server memory this way on servers that enable permessage-brotli. This bypasses the GHSA-hxp9-w8x3-p566 fix. ### Details In 26.7.1 the receive path passes the remaining `maxMessagePayloadSize` budget to `decompress_message_data(..., max_output_len=...)`. deflate and bzip2 stop at that budget. `PerMessageBrotli.decompress_message_dat
O3 Security · Impact-Aware SCA

Is GHSA-pjh6-c8mg-3x7m in your dependencies?

Find it across PyPI, including transitive dependencies.

Autobahn Python: permessage-brotli inflates a whole…