Back to skill

Security audit

PPT Generator

Security checks for vulnerabilities and agentic risk

Overview

This skill coherently generates PPTX files from SVG slide content, with disclosed local scripting and dependency setup, but users should understand it may install Python packages and embed SVG content into generated presentations.

Install this only if you are comfortable with a skill that runs local Python scripts, creates or reuses a virtual environment, may install python-pptx from pip, and writes PPTX/SVG output files. Use trusted slide content, because SVG is copied into the PPTX without strong sanitizer enforcement.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/slides_json_to_pptx.py:39
Finding
Unvalidated SVG Content Is Embedded Verbatim into Generated PPTX Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/slides_json_to_pptx.py:39-53`; `scripts/embed_svg_to_pptx.py:190-194` **Vulnerability Type**: Missing validation and sanitization of untrusted SVG content **Risk Level**: Medium ### Vulnerable Code ```python for index, slide in enumerate(slides, start=1): if not isinstance(slide, dict): raise ValueError(f"slide {index} is not an object") title = slide.get("title") svg = slide.get("svg") if not isinstance(title, str) or not title.strip(): raise ValueError(f"slide {index} is missing a non-empty title") if not isinstance(svg, str) or not svg.strip(): raise ValueError(f"slide {index} is missing a non-empty svg") return slides def _write_svgs(slides: list[dict], svg_dir: Path) -> list[Path]: svg_dir.mkdir(parents=True, exist_ok=True) svg_paths: list[Path] = [] for index, slide in enumerate(slides, start=1): svg_path = svg_dir / f"slide_{index:03d}.svg" svg_path.write_text(slide["svg"], encoding="utf-8") svg_paths.append(svg_path) ``` The resulting file is subsequently copied directly into the PPTX package: ```python for index, svg_path in enumerate(svg_paths, start=1): media_name = f"slide_{index:03d}.svg" shutil.copyfile(svg_path, media_dir / media_name) ``` ### Technical Analysis The loader verifies only that the `svg` property is a non-empty string. It does not parse the document or enforce the SVG restrictions described in `SKILL.md`, such as rejecting scripts, styles, filters, HTML content, or unsupported elements. Consequently, attacker-controlled slide JSON or compromised model output can introduce arbitrary XML and SVG features into the generated presentation. Potentially dangerous content includes: - `script` elements and SVG event-handler attributes. - `foreignObject` elements containing HTML. - External resource references through `href`, `xlink:href`, CSS, or image elements. - DTD declarations o ...[truncated 1769 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the submitted content with an XML parser configured to reject DTDs and external entities. 2. Require exactly one SVG root element with the expected SVG namespace and `viewBox="0 0 1280 720"`. 3. Implement an allowlist of permitted SVG elements and attributes. 4. Explicitly reject: - `script`, `style`, `foreignObject`, and animation elements. - Attributes beginning with `on`, such as `onclick` and `onload`. - DTDs, entities, processing instructions, and non-SVG namespaces. - External or protocol-based references in `href`, `xlink:href`, CSS, and URL-valued attributes. - `data:` URLs unless a narrowly defined, size-limited use case requires them. - The prohibited `filter` element and `filter` attributes. 5. Serialize the validated parsed tree rather than embedding the original input string. 6. Apply limits to SVG size, XML nesting depth, element count, path complexity, and number of slides to mitigate resource-exhaustion attacks. 7. Add negative tests covering scripts, event handlers, `foreignObject`, external images, entity declarations, malformed XML, and oversized SVG documents. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/ensure_skill_env.py:14
Finding
Automatic Installation of an Unhashed Runtime Dependency<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ensure_skill_env.py:14-15, 42-53, 72-75` **Vulnerability Type**: Unverified runtime dependency installation **Risk Level**: Medium ### Vulnerable Code ```python REQUIRED_PACKAGE = "python-pptx>=1.0.2,<1.1.0" IMPORT_CHECK = "import pptx" ``` ```python def _has_python_pptx(python_executable: Path) -> bool: result = subprocess.run( [str(python_executable), "-c", IMPORT_CHECK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False, ) return result.returncode == 0 def _install_dependency(python_executable: Path) -> None: subprocess.run([str(python_executable), "-m", "pip", "install", REQUIRED_PACKAGE], check=True) ``` ```python installed_dependency = False if not _has_python_pptx(python_executable): _install_dependency(python_executable) installed_dependency = True ``` ### Technical Analysis When the `pptx` module cannot be imported, the skill automatically invokes pip. The dependency uses a version range rather than an exact version, and neither direct nor transitive artifacts are protected by hashes. The pip command also inherits the selected interpreter's pip configuration and relevant environment variables. The implementation does not enforce an approved package index, disable untrusted extra indexes, or require explicit approval immediately before network installation. This creates a supply-chain trust boundary at runtime. A compromised upstream release, malicious package-index configuration, intercepted internal mirror, or unsafe transitive dependency could introduce attacker-controlled code. Source distributions may execute build-related code during installation, and installed package code is later imported by `embed_svg_to_pptx.py`. ### Attack Path 1. The selected Python environment does not contain an importable `pptx` module. 2. An attacker controls or compromises a configured pip index, internal mirror, dependency a ...[truncated 1054 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `python-pptx` to one exact, audited version. 2. Maintain a lock file containing exact versions and SHA-256 hashes for all direct and transitive dependencies. 3. Install with hash enforcement, such as `pip install --require-hashes -r requirements.lock`. 4. Enforce an approved HTTPS package index and prevent inherited configuration from silently adding untrusted indexes. 5. Prefer a prebuilt, immutable environment or trusted wheelhouse rather than installing packages during normal skill execution. 6. Require explicit user or administrator approval before performing network-dependent installation. 7. Disable source builds where operationally possible by requiring audited binary wheels. 8. Run dependency installation and document generation inside a least-privileged sandbox with restricted credentials, filesystem access, and outbound networking. 9. Add dependency scanning and integrity verification to the release process. ]]>
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill advertises a full multi-turn PPT generation workflow, but the described operational behavior centers on local scripting, dependency installation, and packaging SVG/JSON into PPTX. This mismatch is dangerous because users and reviewers may authorize it expecting a content-generation helper, while it actually performs code execution and filesystem changes; that confusion can lead to overbroad trust, unsafe invocation, and insufficient review of execution-side risks.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill instructs the agent to create virtual environments, install dependencies, read and write local files, and execute shell commands, but it declares no explicit tool scope or permissions. This creates a least-privilege failure: a caller or reviewer cannot tell from metadata that the skill may modify the filesystem or run code, increasing the risk of unintended execution or abuse through crafted inputs or operational mistakes.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _has_python_pptx(python_executable: Path) -> bool:
    result = subprocess.run(
        [str(python_executable), "-c", IMPORT_CHECK],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _install_dependency(python_executable: Path) -> None:
    subprocess.run([str(python_executable), "-m", "pip", "install", REQUIRED_PACKAGE], check=True)


def ensure_skill_env() -> SkillEnv:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
raise SystemExit(f"target script not found: {script_path}")

    skill_env = ensure_skill_env()
    completed = subprocess.run([skill_env.python, str(script_path), *args.script_args], check=False)
    raise SystemExit(completed.returncode)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The manifest presents the short description in Chinese while the default prompt is in English, but it does not state whether the skill is intended for a specific locale or allow the user to choose a language. This can create a language-policy issue because the skill appears to impose or assume language behavior without explicit opt-in or justification.

Static analysis

No suspicious patterns detected.