Back to skill

Security audit

PPT Polish

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a normal PowerPoint diagram polishing helper, with a narrow helper script and a resource-use caveat for crafted PPTX files.

Install this if you want guidance for rebuilding editable PowerPoint diagrams. Treat the included script as a narrow topology-slide generator, expect Chinese defaults/templates, and avoid running it on untrusted or unusually large PPTX files unless resource limits are in place.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/rebuild_topology_slide.py:35
Finding
Unbounded Decompression of Untrusted PPTX Slide Content## Vulnerability Details **File Location**: `scripts/rebuild_topology_slide.py`, lines 35–43 **Vulnerability Type**: Uncontrolled resource consumption through unbounded ZIP decompression **Risk Level**: Medium ### Vulnerable Code ```python def extract_texts(pptx_path: Path) -> list[str]: texts: list[str] = [] with ZipFile(pptx_path) as zf: slide_names = sorted( n for n in zf.namelist() if n.startswith("ppt/slides/slide") and n.endswith(".xml") ) if not slide_names: return texts data = zf.read(slide_names[0]).decode("utf-8", "ignore") ``` ### Technical Analysis PPTX files are ZIP archives and may originate from untrusted users. The function identifies the first slide XML member and passes its name directly to `ZipFile.read()`. This operation decompresses the entire member into memory before decoding or processing it. The implementation does not enforce a maximum archive size, member count, uncompressed member size, compression ratio, or total decompression budget. It also does not use bounded streaming. Consequently, a small PPTX archive can contain a highly compressed but extremely large `ppt/slides/slide1.xml` member that consumes excessive memory when expanded. This is a resource-exhaustion weakness rather than arbitrary code execution. The regular-expression operation performed afterward may further increase CPU and memory consumption, but complete decompression already occurs first. ### Attack Path 1. An attacker constructs a valid-looking PPTX ZIP archive. 2. The archive includes `ppt/slides/slide1.xml` with highly repetitive content and an extremely large uncompressed size. 3. The attacker supplies the PPTX as the source file for the reconstruction workflow. 4. The Agent invokes `rebuild_topology_slide.py` with the malicious file. 5. `extract_texts()` calls `zf.read(slide_names[0])`, expanding the full XML member in process memory. 6 ...[truncated 657 chars]
Remediation
## Remediation Suggestions 1. Retrieve the selected member's `ZipInfo` before decompression and reject files exceeding a conservative uncompressed-size limit. 2. Enforce maximum compressed size, uncompressed size, compression ratio, archive member count, and aggregate uncompressed-size limits. 3. Replace `ZipFile.read()` with `ZipFile.open()` and read in bounded chunks while tracking the total bytes consumed. 4. Abort immediately when the configured byte budget is exceeded, even if the ZIP metadata claims a smaller size. 5. Catch `BadZipFile`, decompression errors, oversized-input errors, and decoding failures, then return a controlled error without continuing. 6. Run document processing with operating-system memory, CPU, and execution-time limits as defense in depth. 7. Consider parsing XML incrementally after bounded decompression rather than loading the complete slide XML into memory. Example hardening pattern: ```python from zipfile import BadZipFile, ZipFile MAX_SLIDE_XML_BYTES = 10 * 1024 * 1024 MAX_COMPRESSION_RATIO = 100 with ZipFile(pptx_path) as zf: slide_names = sorted( n for n in zf.namelist() if n.startswith("ppt/slides/slide") and n.endswith(".xml") ) if not slide_names: return [] info = zf.getinfo(slide_names[0]) compressed_size = max(info.compress_size, 1) if ( info.file_size > MAX_SLIDE_XML_BYTES or info.file_size / compressed_size > MAX_COMPRESSION_RATIO ): raise ValueError("PPTX slide XML exceeds safety limits") with zf.open(info) as source: data = source.read(MAX_SLIDE_XML_BYTES + 1) if len(data) > MAX_SLIDE_XML_BYTES: raise ValueError("PPTX slide XML exceeds safety limits") xml_text = data.decode("utf-8", "ignore") ```
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The code is related to the declared domain of PowerPoint diagram beautification, but the description is broader than the actual implementation. The implementation is narrowly scoped: it accepts a PPTX input, extracts text only from the first slide via ZIP/XML parsing, classifies labels with hard-coded Chinese keyword heuristics, and produces a new polished single-slide topology/architecture diagram in a fixed layout. It does not handle source images, does not generally restyle editable existing diagrams or arbitrary flowcharts/process visuals, and does not optimize a whole deck. Because the declared purpose suggests a more general rebuild/beautify capability across PPT/PPTX files and source images, while the code performs a much narrower topology-slide reconstruction task, this is a material description-behavior mismatch.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The entire skill specification is written as a Chinese-only deliverable template, including the title and all guidance, with no indication that users may choose another language or locale. Under the policy, forcing a specific language without opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Static analysis

No suspicious patterns detected.