This is less a door left open than a trapdoor that only appears when the floor is already collapsing
CVE-2026-6100 is a real memory-safety flaw in CPython's decompression paths: a MemoryError during lzma.LZMADecompressor, bz2.BZ2Decompressor, and in newer branches the internal zlib decompressor can leave a stale input pointer behind. If application code then reuses the same decompressor object after the exception, a later decompress() call can read or write through freed memory. The CVE record marks CPython versions < 3.15.0 as affected, with branch fixes landing for 3.14, 3.13, and 3.11; Debian also shows backports for selected distro packages.
In vendor scoring this was labeled CRITICAL in Python's advisory stream, and NVD now displays a PSF CVSS-B 9.1, but that overstates enterprise urgency. The deciding friction is not network reachability; it is the compound prerequisite chain: attacker-controlled compressed input, enough heap pressure to force MemoryError, application logic that catches the exception, and unsafe object reuse after failure. That is a narrow, code-pattern-specific exploit path, not a broad internet-scale wormable condition.
4 steps from start to impact.
Reach a Python service that streams attacker data into a reusable decompressor
LZMADecompressor, BZ2Decompressor, or equivalent gzip/zlib-backed path instead of using one-shot helpers. In practice this means custom parsers, gateways, ingestion daemons, or archive-processing microservices with stateful decompression objects. Weaponization here is just crafted input plus ordinary client tooling such as curl or a custom Python sender, not a special exploit kit.- Unauthenticated or authenticated remote input path to compressed content
- Application uses streaming decompressor objects rather than
*.decompress()one-shot helpers - Target is CPython on an affected branch
- Many applications never expose these formats to attackers
- A lot of code uses one-shot helper functions and is explicitly not affected
- Package scanners can find vulnerable CPython versions but cannot prove vulnerable usage
MemoryError.Force a MemoryError during decompression
- Ability to trigger decompression repeatedly or with large/high-expansion inputs
- Process memory limits, cgroup pressure, or host exhaustion make
MemoryErrorreachable
- Modern services often OOM-kill, rate-limit, or reject oversized payloads before this code path is useful
- Container memory limits frequently turn this into a crash/restart problem instead of controlled exploitability
- WAF/API gateways and upload size limits often stop oversized compressed content first
Rely on broken exception handling that reuses the object after failure
MemoryError, the attacker still needs the application to catch the exception and continue using the same decompressor instance for another decompress() call. This is the key exploit gate: many programs abort the request, reset state, or discard the object on any decompression exception. Without this exact anti-pattern, the bug dies here.- Application catches
MemoryErroror broad exceptions and continues execution - Same decompressor object remains live and reachable for later calls
- Most sane error paths tear down the request or recreate the object
- Framework retries often reconstruct objects rather than reusing corrupted state
- This prerequisite implies application-specific code review, not generic version reachability
Trigger stale-pointer access and hope for useful memory corruption
- Precise follow-up input after stale pointer state is created
- Heap/layout conditions that convert corruption into a useful primitive
- Reliability is highly environment-dependent
- ASLR, hardened allocators, process isolation, and frequent restarts cut exploit stability
- No public in-the-wild exploitation or mature public RCE exploit was identified
The supporting signals.
| In-the-wild status | No confirmed active exploitation found in retrieved sources; not in CISA KEV. |
|---|---|
| KEV status | Absent from CISA Known Exploited Vulnerabilities Catalog as checked via the catalog page. |
| Proof-of-concept availability | Patch, issue, and technical details are public via CPython GitHub, but I did not find a public, reliable exploit chain. Red Hat Bugzilla even has a public comment asking whether a PoC exists. |
| EPSS | User-provided EPSS is 0.00164 (~0.164%), which aligns with a low near-term exploitation probability signal. |
| Vendor/CNA scoring reality check | Python's advisory mail called this CRITICAL, and NVD currently shows a Python Software Foundation CVSS v4 base 9.1. Operationally, that looks too high because the path requires both MemoryError and unsafe reuse after the exception. |
| CVSS vector interpretation | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N assumes network reachability, but the hidden attacker requirement is really application misuse plus memory-pressure orchestration. |
| Affected versions | The CNA/CVE data marks CPython < 3.15.0 as affected. Branch commits show fixes for 3.14, 3.13, and 3.11; Debian notes PyPy is not affected because it uses a different pure-Python implementation. |
| Fixed versions | Upstream fix is present in Python 3.14.5 and development 3.15; Debian lists fixes including python3.14 3.14.5~rc1-1, python3.13 3.13.5-2+deb13u2, and python3.9 3.9.2-1+deb11u6, while some older distro branches remain marked vulnerable or minor. |
| Scanning/exposure data | There is no meaningful internet-wide exposure fingerprint for this bug itself. Shodan/Censys-style counts are poor prioritization inputs because the vulnerable condition lives in application logic, not a distinct network service banner. |
| Disclosure and credit | Published 2026-04-13. CVE JSON credits Ryan Hileman and Stan Ulbrych; Seth Larson coordinated/publicly announced it. |
noisgate verdict.
The single biggest downward pressure is that exploitation requires unsafe application behavior after an error, not just a vulnerable Python version. In enterprise fleets this is a narrow, post-precursor bug chain: many hosts may run affected CPython, but only a much smaller subset will both hit MemoryError and reuse the same decompressor object afterward.
Why this verdict
- Downward adjustment: requires attacker-controlled decompression in app code — this is not a generic 'Python installed = remotely reachable' bug.
- Downward adjustment: requires
MemoryErrorfirst — the attacker must create real memory pressure, which many gateways, quotas, and container limits disrupt before controlled exploitation. - Downward adjustment: requires decompressor reuse after failure — this implies a specific coding anti-pattern, and many applications tear down request state or rebuild the object after exceptions.
- Downward adjustment: no KEV / no public exploitation evidence / low EPSS — there is no current threat-intel amplifier pushing this into emergency territory.
- Upward adjustment: memory corruption in ubiquitous runtime — when the bad pattern does exist on a network-facing Python service, impact can move beyond DoS into read/write corruption and potential code execution.
Why not higher?
Because this is not broadly reachable by default. The exploit chain depends on several compounding prerequisites that sharply reduce the exposed population: untrusted compressed input, induced memory pressure, exception survival, and object reuse. That is miles away from a one-request unauthenticated RCE.
Why not lower?
Because the underlying flaw is still memory corruption inside a widely deployed interpreter, not a harmless correctness bug. If an exposed Python service processes attacker-controlled compressed streams with long-lived decompressor objects, the impact ceiling is serious enough that this should stay above backlog-only hygiene.
What to do — in priority order.
- Block or cap hostile compressed inputs — Enforce upload/body/decompression limits at the edge and in the app so attackers cannot easily manufacture the memory-pressure precondition. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, but do this earlier on internet-facing parsers handling untrusted archives.
- Kill decompressor reuse after exceptions — Audit code paths that keep
LZMADecompressor,BZ2Decompressor, or gzip/zlib stateful objects alive across requests or chunks. If any decompression error orMemoryErroroccurs, discard the object and create a fresh one; implement this during normal engineering remediation, well before the 365-day patch window closes. - Prefer one-shot helper APIs — Where streaming semantics are unnecessary, use
lzma.decompress(),bz2.decompress(),gzip.decompress(), orzlib.decompress()because the advisory explicitly says these are not affected. Roll this into secure-code cleanup during the same remediation cycle. - Monitor for precursor memory faults — Alert on worker OOMs, repeated
MemoryError, crash loops, and abnormal decompression failures in Python services that ingest compressed content. This will not prove exploitation, but it gives you an early warning on the exact precondition chain this CVE needs.
- A generic network perimeter block does not solve this if the vulnerable service must legitimately accept compressed uploads or responses.
- Version-only vulnerability scanning does not tell you whether the dangerous object-reuse pattern exists in the application.
- Relying on EDR alone is weak here; many outcomes will look like a crash or worker restart, not cleanly labeled exploit telemetry.
Crowdsourced verification payload.
Run this on the target host with the same interpreter used by the workload, for example: python3 cve_2026_6100_check.py or /opt/app/venv/bin/python cve_2026_6100_check.py. It needs no elevated privileges. The script performs a version-based assessment only; distro backports and custom vendor rebuilds may return UNKNOWN.
#!/usr/bin/env python3
# CVE-2026-6100 version-based checker for CPython
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import platform
import re
import sys
def parse_version(v):
m = re.match(r'^(\d+)\.(\d+)\.(\d+)', v)
if not m:
return None
return tuple(int(x) for x in m.groups())
def out(state, msg, code):
print(f"{state}: {msg}")
sys.exit(code)
impl = platform.python_implementation()
raw_version = platform.python_version()
ver = parse_version(raw_version)
full = sys.version.replace('\n', ' ')
if impl != 'CPython':
out('UNKNOWN', f'Interpreter is {impl}, not CPython; advisory scope differs by implementation. Version: {raw_version}', 2)
if ver is None:
out('UNKNOWN', f'Could not parse Python version: {raw_version}', 2)
major, minor, patch = ver
# Known upstream-fixed thresholds confirmed from retrieved sources:
# - 3.14.5 includes gh-148395 in changelog
# - 3.15.0 and later are not affected per CNA lessThan 3.15.0
# Older maintained distro branches may be backported, but generic upstream
# version-only logic cannot verify that safely.
if (major, minor) >= (3, 15):
out('PATCHED', f'CPython {raw_version} is not affected by the CNA range (< 3.15.0).', 0)
if (major, minor) == (3, 14):
if patch >= 5:
out('PATCHED', f'CPython {raw_version} is at or above 3.14.5, which includes the gh-148395 fix.', 0)
out('VULNERABLE', f'CPython {raw_version} is below 3.14.5.', 1)
# For 3.13/3.12/3.11/3.10/3.9 and vendor-packaged Python builds, backports vary.
# Debian and enterprise distros have issued backported fixes without uniform
# upstream version numbers we can trust from platform.python_version() alone.
if (major, minor) in {(3, 13), (3, 12), (3, 11), (3, 10), (3, 9)}:
msg = (
f'CPython {raw_version} may be vulnerable unless your vendor backported the fix. '
f'Python version string alone is insufficient to verify this build. sys.version={full}'
)
out('UNKNOWN', msg, 2)
if major < 3:
out('UNKNOWN', f'Legacy Python {raw_version}; check vendor advisory/backports manually. sys.version={full}', 2)
out('UNKNOWN', f'Unrecognized CPython branch {raw_version}. sys.version={full}', 2)
If you remember one thing.
gzip/bz2/lzma content and ask one blunt question: do they reuse decompressor objects after exceptions? For this MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, so patch those systems in the normal cycle and clean up the error-handling anti-pattern in the same workstream. If you find a high-risk app pattern — long-lived decompressor objects plus attacker-controlled compressed streams — prioritize it early inside that noisgate remediation SLA window rather than waiting for broad desktop/server fleet turnover.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.