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.
4 steps from start to impact.
Build the weaponized archive
- Attacker can create or obtain a malicious file based on the public advisory/PoC
- Target environment uses 7-Zip 26.00 or earlier
- 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
Land the file on a target host
- Victim can receive external or semi-trusted archives
- The malicious file is not blocked or detonated before reaching the endpoint
- Mail filters, content disarm, and sandboxing reduce success
- Many enterprise users never manually inspect raw archives with 7-Zip
Trigger NTFS parsing in 7-Zip
- 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
- User interaction is the biggest practical brake on mass exploitation
- Some workflows use Windows Explorer ZIP handling or other archivers instead of 7-Zip
7z.exe/7zFM.exe opening a newly delivered archive is useful, but traditional network scanners will miss this entirely.Heap corruption to potential code execution
- Heap layout and memory conditions permit useful corruption
- The process has enough memory for the vulnerable path GHSL described on modern systems
- Exploit reliability may vary by architecture, heap state, and memory availability
- Some runs may degrade to DoS instead of clean code execution
7z.exe/7zFM.exe.The supporting signals.
| In-the-wild status | No public exploitation evidence found in retrieved primary/secondary sources, and not listed in CISA KEV. |
|---|---|
| Public PoC | Yes. GitHub Security Lab's GHSL-2026-140 includes exploit construction details, and multiple security news outlets report public PoC availability. |
| EPSS | No trustworthy EPSS value was retrievable from primary sources at assessment time; treat EPSS as unavailable rather than as low. |
| KEV status | Not in KEV as checked against CISA's Known Exploited Vulnerabilities Catalog. |
| Researcher-scored CVSS context | GHSL 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 versions | All 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 versions | Upstream 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 reality | Inference: 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 timeline | Private report delivered 2026-04-24; fixed release 2026-04-27; public advisory published 2026-05-22 by GitHub Security Lab researcher Jaroslav Lobačevski. |
noisgate verdict.
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.
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.
What to do — in priority order.
- 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.
- 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.
- 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.
- Hunt for vulnerable binaries — Inventory
7z.exe,7zFM.exe,7zz, and packaged7zip/p7zipinstallations 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.
- 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.
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.
#!/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()
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.