← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-6100 · CWE-416 · Disclosed 2026-04-13

Use-after-free

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"= ASSESSED AT MEDIUM: real bug, but exploitation needs memory pressure plus buggy decompressor reuse"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Reach a Python service that streams attacker data into a reusable decompressor

The attacker first needs an application that accepts untrusted compressed content and feeds it into a long-lived 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.
Conditions required:
  • 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
Where this breaks in practice:
  • 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
Detection/coverage: SCA and host inventory can flag affected CPython builds; they cannot determine whether the app reuses decompressor instances after MemoryError.
STEP 02

Force a MemoryError during decompression

The bug only matters after allocation failure. The attacker must supply data and timing that push the Python process into memory pressure at exactly the decompression path that leaves the stale pointer behind. Tooling is ordinary load generation or compressed-bomb style input, but the hard part is deterministic heap pressure on a real service.
Conditions required:
  • Ability to trigger decompression repeatedly or with large/high-expansion inputs
  • Process memory limits, cgroup pressure, or host exhaustion make MemoryError reachable
Where this breaks in practice:
  • 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
Detection/coverage: Application logs, container OOM events, and high-memory alerts may show precursor conditions; network IDS generally has poor visibility into this app-specific trigger.
STEP 03

Rely on broken exception handling that reuses the object after failure

After 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.
Conditions required:
  • Application catches MemoryError or broad exceptions and continues execution
  • Same decompressor object remains live and reachable for later calls
Where this breaks in practice:
  • 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
Detection/coverage: Best found with code review, SAST, or targeted greps for long-lived decompressor objects plus broad exception handling; runtime scanners do not model this logic well.
STEP 04

Trigger stale-pointer access and hope for useful memory corruption

Only now does the use-after-free fire: the next decompression call can read or write via a freed caller buffer. That can plausibly crash the worker and, in a favorable allocator/layout scenario, may permit information disclosure or code execution. Exploit developers would use custom harnesses and heap grooming, but public evidence of a reliable end-to-end exploit is absent.
Conditions required:
  • Precise follow-up input after stale pointer state is created
  • Heap/layout conditions that convert corruption into a useful primitive
Where this breaks in practice:
  • 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
Detection/coverage: Expect crashes, segfaults, abnormal interpreter exits, or sanitizer findings in test harnesses; broad network detection is poor.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed active exploitation found in retrieved sources; not in CISA KEV.
KEV statusAbsent from CISA Known Exploited Vulnerabilities Catalog as checked via the catalog page.
Proof-of-concept availabilityPatch, 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.
EPSSUser-provided EPSS is 0.00164 (~0.164%), which aligns with a low near-term exploitation probability signal.
Vendor/CNA scoring reality checkPython'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 interpretationCVSS: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 versionsThe 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 versionsUpstream 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 dataThere 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 creditPublished 2026-04-13. CVE JSON credits Ryan Hileman and Stan Ulbrych; Seth Larson coordinated/publicly announced it.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (4.8/10)

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.

HIGH Bug exists and patch metadata
MEDIUM Real-world exploitability in production deployments
MEDIUM Likelihood that vulnerable usage patterns exist broadly in enterprise Python services

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 MemoryError first — 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.

05 · Compensating Control

What to do — in priority order.

  1. 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.
  2. 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 or MemoryError occurs, discard the object and create a fresh one; implement this during normal engineering remediation, well before the 365-day patch window closes.
  3. Prefer one-shot helper APIs — Where streaming semantics are unnecessary, use lzma.decompress(), bz2.decompress(), gzip.decompress(), or zlib.decompress() because the advisory explicitly says these are not affected. Roll this into secure-code cleanup during the same remediation cycle.
  4. 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.
What doesn't work
  • 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.
06 · Verification

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.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/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)
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not treat this like fleet-wide emergency patching just because it says UAF. First, identify internet-facing or partner-facing Python services that decompress untrusted 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

  1. NVD CVE detail
  2. Openwall oss-security forwarding Python advisory
  3. CPython issue #148395
  4. CPython fix commit for 3.14 branch
  5. CPython fix commit for 3.13 branch
  6. CPython fix commit for 3.11 branch
  7. Debian security tracker
  8. CISA Known Exploited Vulnerabilities Catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.