← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-48095 · CWE-787 · Disclosed 2026-05-22

7-Zip NTFS archive handler heap buffer overflow

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

Like a booby-trapped shipping box that can explode when the mailroom clerk merely peeks inside

CVE-2026-48095 is a heap buffer write overflow in 7-Zip's NTFS archive handler. GitHub Security Lab says the bug is in CInStream::GetCuSize() and that all versions through 26.00 are affected, with the fix shipped in 7-Zip 26.01 on 2026-04-27. The ugly part is handler reach: a crafted NTFS image can be given a misleading extension and still get parsed because 7-Zip falls back to signature-based format detection.

There is no vendor/CNA baseline CVSS to compare against here, so this is a first-principles assessment. In practice this lands at HIGH, not CRITICAL: the impact can be full code execution and public exploit material exists, but the attacker still needs a user or automation path that causes 7-Zip to open the malicious file. That user-driven prerequisite meaningfully narrows the exposed population versus a remotely reachable service bug.

"Public PoC and file-open trigger make this a real endpoint risk, but it is still user-driven rather than network-reachable."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Build the weaponized archive

The attacker uses the public technical details in GHSL-2026-140 and the disclosed PoC generator to create a crafted NTFS image that abuses the compressed-stream buffer sizing bug. The archive can be disguised with misleading extensions because 7-Zip may still route it to the NTFS handler via signature fallback.
Conditions required:
  • Attacker can create or obtain a malicious file based on the public advisory/PoC
  • Target environment uses 7-Zip 26.00 or earlier
Where this breaks in practice:
  • This is not a one-packet internet exploit; the attacker must deliver a file somehow
  • Working code-exec reliability can depend on platform details and available memory
Detection/coverage: Email sandboxing, secure web gateway detonation, and archive-analysis pipelines may catch known samples, but generic vuln scanners usually do not validate parser reachability on endpoints.
STEP 02

Land the file on a target host

Typical delivery is phishing attachment, chat transfer, shared drive drop, mod/crack package, or a software artifact passed to a build/admin workstation. The attacker does not need network adjacency to the host, but does need a believable file-delivery channel.
Conditions required:
  • Victim can receive external or semi-trusted archives
  • The malicious file is not blocked or detonated before reaching the endpoint
Where this breaks in practice:
  • Mail filters, content disarm, and sandboxing reduce success
  • Many enterprise users never manually inspect raw archives with 7-Zip
Detection/coverage: EDR, mail security, browser download protection, and attachment sandboxing provide the best chance to stop this step.
STEP 03

Trigger NTFS parsing in 7-Zip

The victim opens, previews, tests, or otherwise causes 7-Zip to inspect the file. Per GHSL, extraction is not the only concern; opening the crafted image is enough to reach the vulnerable NTFS parser path.
Conditions required:
  • A user, script, or workflow opens the file with 7-Zip or a linked 7-Zip component
  • The file reaches the NTFS handler despite its displayed extension
Where this breaks in practice:
  • User interaction is the biggest practical brake on mass exploitation
  • Some workflows use Windows Explorer ZIP handling or other archivers instead of 7-Zip
Detection/coverage: Application telemetry showing 7z.exe/7zFM.exe opening a newly delivered archive is useful, but traditional network scanners will miss this entirely.
STEP 04

Heap corruption to potential code execution

The malformed NTFS data causes under-allocation, then attacker-controlled data overwrites adjacent heap memory. GHSL describes a vtable-hijack path that can lead to arbitrary code execution; in less favorable conditions it may only crash the application.
Conditions required:
  • Heap layout and memory conditions permit useful corruption
  • The process has enough memory for the vulnerable path GHSL described on modern systems
Where this breaks in practice:
  • Exploit reliability may vary by architecture, heap state, and memory availability
  • Some runs may degrade to DoS instead of clean code execution
Detection/coverage: EDR can catch the post-corruption outcome better than the bug itself: crashes, anomalous child processes, memory protections, or suspicious module loads from 7z.exe/7zFM.exe.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public exploitation evidence found in retrieved primary/secondary sources, and not listed in CISA KEV.
Public PoCYes. GitHub Security Lab's GHSL-2026-140 includes exploit construction details, and multiple security news outlets report public PoC availability.
EPSSNo trustworthy EPSS value was retrievable from primary sources at assessment time; treat EPSS as unavailable rather than as low.
KEV statusNot in KEV as checked against CISA's Known Exploited Vulnerabilities Catalog.
Researcher-scored CVSS contextGHSL published CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 / High. This is not a vendor/CNA baseline, so noisgate keeps the verdict as = ASSESSED AT HIGH rather than upgraded/downgraded.
Affected versionsAll 7-Zip versions through 26.00 are described as affected by GHSL; Debian also marks older packaged builds and p7zip transitions as vulnerable where they still resolve to affected code.
Fixed versionsUpstream fixed in 7-Zip 26.01. Debian tracker shows 7zip 26.01+dfsg-1 as fixed in unstable and notes the p7zip transitional package state.
Exposure / scanning realityInference: this is primarily an endpoint parser bug, not an internet-facing service. Shodan/Censys/FOFA-style internet exposure counts are therefore not useful prioritization signals here; your real exposure is the installed base of 7-Zip on user, admin, and build hosts.
Disclosure timelinePrivate report delivered 2026-04-24; fixed release 2026-04-27; public advisory published 2026-05-22 by GitHub Security Lab researcher Jaroslav Lobačevski.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (8.3/10)

The single most important downward pressure is that exploitation is user-driven file handling, not unauthenticated access to a listening service. It still lands in HIGH because the product is widespread, the trigger is merely opening a crafted file, handler fallback defeats extension-based assumptions, and public exploit guidance exists.

HIGH Affected versions through 26.00 and fix in 26.01
HIGH Public PoC/advisory details and exploitation mechanism
MEDIUM Real-world exploit reliability across mixed enterprise endpoints

Why this verdict

  • Starts high on impact: this is memory corruption in a ubiquitous archive parser, with a plausible code-exec path documented by GHSL rather than a benign parser crash.
  • Downward adjustment for attacker position: the prerequisite is file delivery plus user or workflow interaction. That implies phishing, file-share abuse, or supply-chain content handling rather than direct unauthenticated remote exploitation against your perimeter.
  • Upward adjustment for reachable population: 7-Zip is broadly installed on endpoints and admin workstations, and GHSL says signature-based fallback can send deceptively named files into the NTFS handler anyway.
  • Upward adjustment for weaponization: technical detail is public and PoC availability is widely reported, reducing attacker cost.
  • Downward adjustment for blast radius: compromise is typically one host at a time from a delivered file, not instant estate-wide exploitation of every exposed server.

Why not higher?

This is not KEV-listed, and I found no solid public evidence of active campaigns. More importantly, the attacker still needs a delivery path and a victim or automation workflow that actually opens the malicious file with vulnerable 7-Zip code; that is materially different from a remotely reachable service RCE.

Why not lower?

Opening the file can be enough, which is a much lower bar than 'extract and run something.' The extension-bypass behavior and wide 7-Zip footprint make this more than a niche edge case, so treating it as MEDIUM would understate real endpoint risk.

05 · Compensating Control

What to do — in priority order.

  1. Block untrusted archive handling in 7-Zip — Use mail, web, and endpoint policy to prevent 7-Zip from opening archives from untrusted sources until patched, especially on helpdesk, SOC, admin, and build hosts. For a HIGH verdict, deploy this compensating control within 30 days where patch rollout will lag.
  2. Quarantine suspicious archives before user access — Route inbound archives and disk-image-like attachments through sandboxing or detonation, and hold files with mismatched content/signature versus extension. This matters here because GHSL says renamed files can still reach the NTFS handler; deploy within 30 days.
  3. Remove or restrict 7-Zip on high-risk tiers — On servers, jump boxes, CI runners, and privileged admin workstations, uninstall 7-Zip where it is not operationally required or restrict execution via allowlisting. This cuts exposure on the systems with the highest blast radius; implement within 30 days.
  4. Hunt for vulnerable binaries — Inventory 7z.exe, 7zFM.exe, 7zz, and packaged 7zip/p7zip installations across endpoints and Linux/macOS hosts so patching is driven by facts instead of guesswork. Start immediately and complete the discovery pass within 30 days.
What doesn't work
  • WAFs don't help because this is not an HTTP-facing bug.
  • Network IDS alone won't save you because the trigger is local file parsing after delivery, often over normal email/web/file-share channels.
  • MFA is irrelevant to the actual exploit path; it may reduce initial phishing account abuse but does not harden the vulnerable parser.
06 · Verification

Crowdsourced verification payload.

Run this on the target host itself, or push it with your endpoint management tool. Invoke with python3 check_cve_2026_48095.py on Linux/macOS or py -3 .\check_cve_2026_48095.py on Windows; standard user rights are usually enough, though package-manager queries may be more reliable with local admin/root on some systems.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# CVE-2026-48095 checker for 7-Zip / 7zz / packaged 7zip
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

import os
import platform
import re
import shutil
import subprocess
import sys

TARGET_FIXED = (26, 1)

def run(cmd):
    try:
        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=10)
        return p.returncode, p.stdout.strip()
    except Exception:
        return 999, ""

def parse_version(text):
    if not text:
        return None
    # Prefer upstream-looking versions such as 26.01, 25.01, 22.01
    m = re.search(r'(?:^|[^0-9])((\d{2})\.(\d{2}))(?:[^0-9]|$)', text)
    if m:
        return (int(m.group(2)), int(m.group(3)), m.group(1))
    # Debian backport patterns like really25.01
    m = re.search(r'really(\d{2})\.(\d{2})', text)
    if m:
        return (int(m.group(1)), int(m.group(2)), f"{m.group(1)}.{m.group(2)}")
    return None

def version_status(ver):
    if ver is None:
        return "UNKNOWN"
    major, minor, _ = ver
    if (major, minor) >= TARGET_FIXED:
        return "PATCHED"
    return "VULNERABLE"

def check_binary(path):
    for args in ([path], [path, '--help'], [path, '-h'], [path, 'i']):
        rc, out = run(args)
        ver = parse_version(out)
        if ver:
            return version_status(ver), f"binary={path} version={ver[2]}"
    return None, None

def windows_candidates():
    candidates = []
    envs = [os.environ.get('ProgramFiles'), os.environ.get('ProgramFiles(x86)'), os.environ.get('ChocolateyInstall')]
    for base in envs:
        if not base:
            continue
        candidates.extend([
            os.path.join(base, '7-Zip', '7z.exe'),
            os.path.join(base, '7-Zip', '7zFM.exe'),
            os.path.join(base, 'bin', '7z.exe'),
        ])
    for name in ['7z.exe', '7zz.exe', '7z', '7zz']:
        p = shutil.which(name)
        if p:
            candidates.append(p)
    seen = set()
    uniq = []
    for c in candidates:
        if c and c not in seen:
            uniq.append(c)
            seen.add(c)
    return uniq

def unix_candidates():
    candidates = []
    for name in ['7zz', '7z']:
        p = shutil.which(name)
        if p:
            candidates.append(p)
    return candidates

def check_packages_linux():
    # dpkg / apt
    if shutil.which('dpkg-query'):
        rc, out = run(['dpkg-query', '-W', '-f=${Package} ${Version}\n', '7zip', 'p7zip'])
        if out:
            lines = [x.strip() for x in out.splitlines() if x.strip() and 'no packages found' not in x.lower()]
            for line in lines:
                ver = parse_version(line)
                if ver:
                    return version_status(ver), f"package={line}"
    # rpm
    if shutil.which('rpm'):
        for pkg in ['7zip', 'p7zip']:
            rc, out = run(['rpm', '-q', pkg])
            if rc == 0 and out:
                ver = parse_version(out)
                if ver:
                    return version_status(ver), f"package={out}"
    # apk
    if shutil.which('apk'):
        rc, out = run(['apk', 'info', '-e', '7zip'])
        if rc == 0:
            rc2, out2 = run(['apk', 'info', '-v', '7zip'])
            ver = parse_version(out2)
            if ver:
                return version_status(ver), f"package={out2}"
    return None, None

def main():
    system = platform.system().lower()

    if 'windows' in system:
        for path in windows_candidates():
            if os.path.exists(path):
                status, detail = check_binary(path)
                if status:
                    print(f"{status}: {detail}")
                    sys.exit(0 if status == 'PATCHED' else 1)
        print('UNKNOWN: 7-Zip binary not found or version could not be parsed')
        sys.exit(2)

    # Linux / macOS / other Unix-like
    status, detail = check_packages_linux()
    if status:
        print(f"{status}: {detail}")
        sys.exit(0 if status == 'PATCHED' else 1)

    for path in unix_candidates():
        status, detail = check_binary(path)
        if status:
            print(f"{status}: {detail}")
            sys.exit(0 if status == 'PATCHED' else 1)

    print('UNKNOWN: no supported 7-Zip installation located or version string unparseable')
    sys.exit(2)

if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as an endpoint-focused HIGH: identify every place 7-Zip is installed, prioritize user workstations that handle inbound files plus admin/build/jump hosts, and put archive-handling guardrails in place where patching will lag. Under the noisgate mitigation SLA, deploy compensating controls within 30 days; under the noisgate remediation SLA, get vulnerable installs to 7-Zip 26.01 or later within 180 days. There is no KEV or confirmed active exploitation override in the retrieved sources, so you do not need an hours-level emergency response, but you also should not leave this in quarterly backlog purgatory.

Sources

  1. GitHub Security Lab advisory GHSL-2026-140
  2. 7-Zip official homepage / release history
  3. 7-Zip official download page
  4. 7-Zip GitHub releases
  5. Debian security tracker for CVE-2026-48095
  6. CISA Known Exploited Vulnerabilities Catalog
  7. SecurityOnline PoC coverage
  8. TechSpot summary of disclosure and PoC availability
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.