T09 · Insecure Skill Coding Practices
- Location
scripts/compress.py:329- Finding
Unbounded PPTX Decompression and In-Memory Archive Retention
- Content
View full analysis
Vulnerability Details
File Location:
scripts/compress.py, lines 329-344
Vulnerability Type: Uncontrolled resource consumption through malicious ZIP/PPTX input
Risk Level: MediumVulnerable Code:
python entries = {} images_processed = 0 images_saved = 0 videos_processed = 0 videos_saved = 0 tmp_dir = tempfile.mkdtemp(prefix="pptc_") try: with zipfile.ZipFile(input_path, "r") as zin: for info in zin.infolist(): name = info.filename if name.endswith("/"): continue data = zin.read(name)Technical Analysis
The application treats the supplied PPTX as a ZIP archive and calls
zin.read(name)for every non-directory member. Each member is fully decompressed into memory. The resulting content is subsequently retained in theentriesdictionary until the entire output archive is written.The implementation does not enforce limits on:
- The number of archive members
- The uncompressed size of an individual member
- The cumulative uncompressed size
- The ratio between compressed and uncompressed sizes
- The amount of memory available for retained archive data
Consequently, a small malicious PPTX containing highly compressible data can expand to a very large size. An archive with many moderately large entries can produce the same outcome. Media files may also be copied to temporary storage for processing, potentially causing disk exhaustion in addition to memory exhaustion.
The archive is not extracted using member-controlled filesystem paths, so this finding is not a ZIP path traversal vulnerability.
Attack Path
- An attacker creates a valid ZIP-based PPTX containing one or more entries with extremely large declared or actual uncompressed sizes.
- The attacker provides the presentation to a user or service that invokes this Skill.
- The compressor enumerates the entries with
zin.infolist().
...[truncated 743 chars]
- Remediation
View remediation
Remediation Suggestions
- Check
ZipInfo.file_sizebefore reading each member and reject entries above a documented per-entry limit. - Track cumulative uncompressed size and stop processing when a global limit is exceeded.
- Reject archives containing an excessive number of members.
- Calculate and constrain the compression ratio using
file_sizeandcompress_size, taking care to handle zero-size values. - Process and write entries incrementally rather than retaining the entire archive in
entries. - Apply operating-system resource controls, including memory, CPU, execution-time, and temporary-disk quotas, when handling untrusted files.
- Preserve Pillow's decompression-bomb protections and consider treating
PIL.Image.DecompressionBombWarningas an error. - Validate limits before invoking ffmpeg and constrain the size of temporary video files.
- Return a clear validation error when an archive exceeds any configured limit.
- Check
