Back to skill

Security audit

123

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real PowerPoint generator, but its filename inputs can escape the skill folder and overwrite writable files.

Review before installing. Use only trusted template files, avoid passing absolute or ../ paths, and run it in a restricted workspace because a crafted output filename could overwrite files the process can write. Pin the dependency before production use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/index.py:428
Finding
Caller-Controlled Paths Permit Unauthorized File Read and Write## Vulnerability Details **File Location**: `src/index.py`, lines 428-440 **Vulnerability Type**: Path traversal and unrestricted filesystem access **Risk Level**: High ### Vulnerable Code ```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 ``` The resulting paths are subsequently used without confinement checks: ```python prs = Presentation(str(template_path)) ... prs.save(str(output_path)) ``` ### Technical Analysis Both `template_file` and `output_filename` are controlled by the caller. Joining an untrusted path to `skill_root` does not ensure that the result remains inside the skill directory: - A path containing `../` can traverse outside the intended directory. - If the supplied path is absolute, Python's `pathlib` discards the preceding `skill_root`. - The implementation does not call `resolve()` and verify that the resolved path is beneath an approved directory. - The output path has no extension restriction, overwrite protection, or collision check. The template input must be a file that `python-pptx` can successfully parse, which limits arbitrary reading to compatible PowerPoint files. Nevertheless, the caller can select any accessible compatible file outside the skill directory. More critically, the output operation can create or overwrite any file writable by the skil ...[truncated 1415 chars]
Remediation
## Remediation Suggestions 1. Define separate, explicit directories for approved templates and generated output. 2. Reject absolute caller-supplied paths. 3. Resolve each candidate path and verify that it remains beneath the corresponding approved directory. 4. Restrict both template and output files to the `.pptx` extension. 5. Treat caller input as a filename rather than an unrestricted path when subdirectories are unnecessary. 6. Refuse to overwrite existing files unless overwrite behavior is explicitly authorized. 7. Ensure the output path cannot equal the template path. 8. Run the skill under a dedicated account with minimal filesystem permissions. Example hardening logic: ```python def confined_pptx_path(base: Path, supplied: str) -> Path: if not supplied: raise ValueError("A filename is required") untrusted = Path(supplied) if untrusted.is_absolute(): raise ValueError("Absolute paths are not allowed") if untrusted.suffix.lower() != ".pptx": raise ValueError("Only .pptx files are allowed") resolved_base = base.resolve() candidate = (resolved_base / untrusted).resolve() if not candidate.is_relative_to(resolved_base): raise ValueError("Path escapes the approved directory") return candidate template_path = confined_pptx_path(template_directory, template_file) output_path = confined_pptx_path(output_directory, output_filename) if output_path == template_path: raise ValueError("Output path cannot overwrite the template") if output_path.exists(): raise FileExistsError(f"Output already exists: {output_path}") ``` Where atomic output creation is required, write to a securely created temporary file inside the approved output directory and atomically rename it after successful generation.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unbounded Third-Party Dependency Reduces Supply-Chain Integrity## Vulnerability Details **File Location**: `requirements.txt`, line 1; installation documented in `README.md`, lines 20-22 **Vulnerability Type**: Unpinned third-party dependency **Risk Level**: Low ### Vulnerable Code `requirements.txt`: ```text python-pptx>=0.6.23 ``` `README.md`: ```bash python3 -m pip install -r requirements.txt ``` ### Technical Analysis The lower-bound-only requirement permits installation of any future `python-pptx` release that satisfies the minimum version. No lock file or package hashes are supplied. As a result, two installations performed at different times can resolve to different artifacts. This weakens build reproducibility and makes the effective dependency set dependent on the state and configuration of the package index at installation time. The reviewed project does not contain evidence that `python-pptx` itself is malicious. The risk arises from trusting an unconstrained future version or an untrusted package index without artifact verification. ### Attack Path 1. A user follows the documented installation command. 2. `pip` queries the configured package index and selects the newest release satisfying `python-pptx>=0.6.23`. 3. A compromised upstream release, package-index account, mirror, or installation environment supplies a malicious or otherwise unsafe future artifact. 4. Because no exact version or hash is enforced, the artifact is accepted. 5. Malicious package installation or runtime code can execute with the privileges of the user performing installation or running the skill. This path requires compromise or unsafe configuration of the dependency supply chain; it is not directly exploitable solely through normal skill input. ### Impact Assessment If a malicious dependency artifact is installed, its code can run with the permissions of the installing or runtime account. Potential impact includes access to files, environment variables, process creden ...[truncated 215 chars]
Remediation
## Remediation Suggestions 1. Pin `python-pptx` to a specifically reviewed version rather than using only a lower bound. 2. Generate and commit a lock file that captures all transitive dependencies. 3. Record cryptographic hashes and install with hash verification. 4. Use a trusted, authenticated package index and disable unintended fallback indexes. 5. Run dependency vulnerability and update checks as part of release maintenance. 6. Test and deliberately approve dependency upgrades before changing the lock file. A hash-locked requirements entry should follow this pattern: ```text python-pptx==REVIEWED_VERSION \ --hash=sha256:REVIEWED_DISTRIBUTION_HASH ``` Installation can then enforce integrity: ```bash python3 -m pip install --require-hashes -r requirements.txt ```
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The manifest describes a PPT generation skill, but the detected behavior includes analyzing existing PowerPoint content, extracting slide text/structure, and writing a JSON catalog instead of only generating decks from provided XML/prompts. This mismatch is dangerous because it can conceal data extraction or unintended processing of proprietary template content, preventing users and reviewers from accurately assessing what the skill actually does.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill advertises file read/write capability through its effective behavior but does not declare any explicit tool scope or permissions in the manifest. That makes the trust boundary unclear and can lead to overbroad filesystem access being granted implicitly, which is risky for a skill that handles templates and writes output files.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The handler builds output_path as skill_root / output_filename using caller-controlled input without validating that the final path stays within the skill directory. In Python, absolute paths override the base path and relative traversal such as ../../ can escape it, allowing arbitrary file overwrite wherever the process has write access. In an agent setting, that exceeds the expected scope of 'generate a PPT' and can be used to clobber application files, user files, or other artifacts.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
The XML content mixes Chinese slide titles and labels with English titles and subtitles, indicating an implicit locale choice in the generated presentation content. There is no natural-language indication that the user can choose the output language or that the bilingual/mixed-language format is required for a region-specific purpose.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=0.6.23
Confidence
96% confidence
Finding
The dependency is specified with a lower-bound range (python-pptx>=0.6.23) rather than being pinned to an exact version, which makes builds non-reproducible and can pull in newly published upstream releases without review. In a skill that generates PowerPoint decks, this is not directly dangerous by itself, but it increases supply-chain risk because a compromised or breaking future release of python-pptx could be installed automatically.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The code hardcodes the title fallback text "目录", which forces Chinese output in at least one generated slide element regardless of user preference. The file does not offer locale selection or document that the tool is intentionally region-specific.

Missing User Warnings

Low
Confidence
81% confidence
Finding
The skill saves a generated presentation to a user-controlled path via prs.save(str(output_path)), which is a file write operation. Although this is part of the generator's functionality, there is no confirmation prompt, comment/docstring warning, or user-facing disclosure near the write path itself about overwriting or creating files.

Static analysis

No suspicious patterns detected.