Back to skill

Security audit

corporate-ppt-generator

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to generate PowerPoint decks, but its unrestricted input and output paths can read templates and overwrite files outside the skill directory.

Review before installing. Use only trusted template_file and output_filename values, avoid absolute paths or ../ components, and run the skill in a restricted workspace. The publisher should confine template reads and generated outputs to approved directories and pin dependencies before broad use.

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

Error
Location
src/index.py:449
Finding
Path Traversal Enables Out-of-Scope File Access and Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `src/index.py:449-454`, with the unsafe write occurring at `src/index.py:444` **Vulnerability Type**: Unrestricted filesystem paths and path traversal **Risk Level**: High ### Vulnerable Code ```python prs.save(str(output_path)) ``` ```python async def handler(input: dict[str, Any], _context: Any) -> dict[str, Any]: skill_root = Path(__file__).resolve().parent.parent template_file = input.get("template_file") or "PPT_Template.pptx" template_path = skill_root / template_file if not template_path.exists(): raise FileNotFoundError(f"Template not found: {template_path}") mode = (input.get("mode") or "xml").strip().lower() if mode != "xml": raise ValueError("Only xml mode is supported") title = input.get("title", "Corporate Deck") output_filename = input.get("output_filename", "openclaw_generated_xml.pptx") output_path = skill_root / output_filename ``` ### Technical Analysis The `template_file` and `output_filename` parameters are accepted from caller-controlled input and combined with `skill_root` without validation or a resolved-path containment check. A path containing `../` components can escape the skill directory. In addition, when the right-hand operand of a `pathlib.Path` join is absolute, Python discards the preceding `skill_root`. Consequently, both relative traversal paths and absolute paths can select files outside the intended project directory. The template path is passed to `Presentation`, allowing any readable, structurally valid PPTX file accessible to the process to be loaded. The output path is passed directly to `prs.save`, allowing PPTX data to be written to or overwrite any filesystem path writable by the process. The check performed for `template_path` only establishes that the path exists. It does not verify that the resolved path remains under the skill directory, that it is a regular file, or that it has an approved extension. ...[truncated 1709 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Reject absolute paths for both `template_file` and `output_filename`. 2. Resolve each candidate path before using it and enforce containment within dedicated approved directories: ```python def confined_path(base: Path, supplied: str, extension: str) -> Path: if not isinstance(supplied, str) or not supplied: raise ValueError("A non-empty filename is required") relative = Path(supplied) if relative.is_absolute(): raise ValueError("Absolute paths are not allowed") base = base.resolve() candidate = (base / relative).resolve() try: candidate.relative_to(base) except ValueError as exc: raise ValueError("Path escapes the approved directory") from exc if candidate.suffix.lower() != extension: raise ValueError(f"Only {extension} files are allowed") return candidate ``` 3. Use separate directories for trusted templates and generated output. Do not allow callers to select arbitrary files from the entire skill directory. 4. Restrict template files to an allowlist of known templates where possible. 5. Require the template path to be a regular file and reject symbolic links when the deployment threat model permits untrusted local filesystem changes. 6. Generate server-side output names instead of accepting unrestricted caller-provided paths. 7. Use exclusive file creation or explicit overwrite controls to avoid silently replacing existing files. 8. Run the skill under a dedicated low-privilege account with read access only to approved templates and write access only to a dedicated output directory. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unpinned Third-Party Dependency Creates Supply-Chain Exposure<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1`; installation instruction at `README.md:25` **Vulnerability Type**: Unbounded third-party dependency version **Risk Level**: Low ### Vulnerable Code ```text python-pptx>=0.6.23 ``` The documented installation command is: ```bash python3 -m pip install -r requirements.txt ``` ### Technical Analysis The dependency uses a minimum-version constraint rather than an exact reviewed version. As a result, installation may select any current or future `python-pptx` release satisfying `>=0.6.23`. No lock file or package hashes are present in the audited project. Builds are therefore not reproducible and do not cryptographically verify the exact dependency artifact expected by the project. This is not evidence that the current `python-pptx` package is malicious. The risk arises because future installation behavior can change without any modification to this repository. A compromised release, compromised distribution account, or unexpectedly incompatible future release could be installed automatically. Python packages execute imported code at runtime and may also execute build-backend logic during installation when a source distribution is selected. Such code runs with the privileges of the user or service performing installation or executing the skill. ### Attack Path 1. A maintainer or deployment system follows the documented command: ```bash python3 -m pip install -r requirements.txt ``` 2. The package resolver queries the configured package index and chooses a release satisfying `python-pptx>=0.6.23`. 3. If a future eligible release or its distribution artifact is compromised, that artifact is downloaded because no exact pin or hash restricts selection. 4. Package-controlled build logic may run during installation, or compromised module code may run when the skill imports: ```python from pptx import Presentation ``` 5. The malicious dependency code executes with the in ...[truncated 696 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `python-pptx` to an exact, reviewed version: ```text python-pptx==<reviewed-version> ``` 2. Generate and commit a lock file that includes all transitive dependencies. 3. Require cryptographic hashes during installation, for example through a hash-locked requirements file and: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 4. Review dependency updates before changing the lock file rather than accepting future releases automatically. 5. Install dependencies only from a trusted, explicitly configured package index. 6. Perform dependency vulnerability and provenance scanning in CI. 7. Build and install dependencies in an isolated, non-privileged environment, avoiding root-level package installation. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
95% confidence
Finding
The declared purpose says the skill generates branded PPT decks, but the detected behavior indicates additional functionality such as template introspection, slide/content analysis, and writing metadata JSON outputs that are not disclosed. Hidden or mismatched behavior is dangerous because it can mask data harvesting from templates, unintended content extraction, or outputs that differ from user expectations, reducing transparency and increasing the chance of misuse.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill advertises file read/write behavior but does not declare any explicit tool scope or permissions boundaries in its manifest. That creates an authorization ambiguity where an agent or reviewer cannot easily determine what filesystem access is intended, increasing the risk of over-broad file access or unsafe writes during execution.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code saves a generated .pptx file to `output_path`, which is derived from user input, but there is no confirmation prompt, warning comment/docstring, or user-facing disclosure around this file write. This is a safety-relevant operation because it modifies the filesystem and could overwrite an existing file silently.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
This XML content includes substantial Chinese text alongside English labels and titles, but there is no natural-language indication that the language choice is optional, user-selected, or required for a specific regional context. Under the policy rule for language/locale constraints, forcing a language or mixed locale without opt-in can be a policy concern.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=0.6.23
Confidence
90% confidence
Finding
The dependency is specified with a lower-bound only (python-pptx>=0.6.23), which permits installation of any future release, including versions that may introduce security regressions, breaking changes, or compromised upstream packages. While this is a supply-chain hygiene issue rather than an immediate exploit, it reduces build reproducibility and can expose the skill to unreviewed dependency updates.

Missing User Warnings

Low
Confidence
77% confidence
Finding
The CLI entrypoint reads a local file specified by `--block-xml-file`, but the code provides no warning, comment, or other disclosure that it will access local filesystem content. This is a safety-relevant file access operation under the missing-warning rule for code files.

Static analysis

No suspicious patterns detected.