Back to skill

Security audit

PPT 生成 AI PPT Slides

Security checks for vulnerabilities and agentic risk

Overview

This skill largely matches its PPT-generation purpose, but it needs review because it stores and transmits a dLazy API key and can send it, prompts, and uploaded images to an unvalidated configured endpoint.

Review before installing. Use only the default https://dlazy.com endpoint unless you intentionally trust a self-hosted dLazy server, avoid confidential source documents or images unless approved for dLazy processing, rotate the dLazy API key if the base URL may have been changed, and prefer a locked or reviewed dependency install rather than the floating requirements.txt bootstrap.

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
scripts/dlazy_client.py:61
Finding
Bearer credential can be transmitted to an arbitrary user-configured endpoint<![CDATA[ ## Vulnerability Details **File Location**: - `scripts/dlazy_client.py:61-79` - `scripts/dlazy_client.py:94-104` - `scripts/dlazy_ppt_runtime.py:194-206` - `docs/image-model-configuration.md:23-24, 42-47` **Vulnerability Type**: Unvalidated credential destination and insecure transport configuration **Risk Level**: High ### Vulnerable Code ```python def base_url() -> str: return (os.getenv("DLAZY_BASE_URL") or DEFAULT_BASE_URL).strip().rstrip("/") def api_key() -> Optional[str]: return (os.getenv("DLAZY_API_KEY") or "").strip() or None def _headers() -> Dict[str, str]: key = api_key() if not key: raise DlazyError( f"DLAZY_API_KEY is not set. Get a key from {API_KEY_URL} and save it with " "`python3 scripts/dlazy_ppt_runtime.py config --api-key <key>`." ) return { "Authorization": f"Bearer {key}", "Content-Type": "application/json", "X-CLI-Version": CLI_VERSION, } ``` ```python def upload_file(path: Path) -> str: """Upload a local image to dLazy storage and return its public URL.""" requests = _requests() filename = path.name content_type = mimetypes.guess_type(filename)[0] or "application/octet-stream" resp = requests.post( f"{base_url()}/api/cli/upload-url", headers=_headers(), json={"filename": filename, "contentType": content_type}, timeout=60, ) ``` ```python def _manifest_request(base_url: str, api_key: str, timeout: int) -> Optional[dict]: """Fetch the tool manifest - the cheapest call that proves the key works.""" endpoint = base_url.rstrip("/") + "/api/cli/tool/manifest" req = urllib.request.Request( endpoint, headers={ "Authorization": f"Bearer {api_key}", "X-CLI-Version": CLI_VERSION, }, method="GET", ) try: with urllib.request.urlopen(req, timeout=timeout) as resp: print(f"tool manifest: HTTP {res ...[truncated 2887 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the base URL with `urllib.parse.urlsplit` before any request. 2. Permit only `https` by default. Reject plaintext HTTP except for an explicit development-only localhost option. 3. Reject URLs containing embedded user information, fragments, or unsupported schemes. 4. Use `https://dlazy.com` as the only destination for dLazy-issued credentials by default. 5. Require a distinct credential option for self-hosted deployments rather than automatically forwarding `DLAZY_API_KEY`. 6. If custom remote hosts must be supported, display the normalized hostname and require explicit user confirmation before saving or transmitting a credential. 7. Consider an administrator-managed allowlist for approved self-hosted domains. 8. Validate that upload URLs use HTTPS and, where feasible, belong to an approved storage-domain allowlist. 9. Document that changing the base URL changes the party receiving the API key, prompts, and uploaded images. 10. Add tests confirming rejection of: - `http://example.com` - URLs with embedded credentials - unsupported schemes such as `file:` or `ftp:` - unapproved external domains when allowlisting is enabled ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
Runtime bootstrap installs mutable, unpinned third-party dependencies<![CDATA[ ## Vulnerability Details **File Location**: - `requirements.txt:1-4` - `scripts/dlazy_ppt_runtime.py:120-143` **Vulnerability Type**: Unpinned dependency installation and non-reproducible supply chain **Risk Level**: Medium ### Vulnerable Code ```text python-pptx>=1.0.2 Pillow>=10.0.0 requests>=2.32.0 filelock>=3.16.0 ``` ```python def _bootstrap(args: argparse.Namespace) -> int: home = _runtime_home() _ensure_dirs(home) python = _venv_python(home) if not python.exists(): print(f"Creating virtual environment: {home / '.venv'}") venv.EnvBuilder(with_pip=True, clear=False).create(home / ".venv") else: print(f"Virtual environment already exists: {home / '.venv'}") requirements = _requirements_path() if not requirements.exists(): _die(f"requirements.txt not found: {requirements}") cmd = [str(python), "-m", "pip", "install", "-r", str(requirements)] if args.upgrade: cmd.insert(4, "-U") print(f"Installing dependencies from: {requirements}") subprocess.run(cmd, check=True) print(f"Runtime ready: {home}") return 0 ``` ### Technical Analysis All four dependencies use open-ended lower bounds. Each bootstrap can therefore resolve to different package versions depending on installation time, index state, platform, and dependency resolver behavior. The installation also lacks cryptographic package hashes and does not constrain the package index. Python package installation is a code-execution boundary. Package build backends, installation hooks, imported modules, and native components can execute code under the account running the bootstrap. Although no currently listed package was shown to be malicious, the configuration does not ensure that installed artifacts are the exact versions reviewed by the Skill publisher. The `--upgrade` option further increases mutability by explicitly requesting newer satisfying versions. ### Attack Path 1. A user or Agent follows th ...[truncated 1298 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace lower-bound requirements with exact, reviewed versions. 2. Generate a lock file containing hashes for every direct and transitive dependency. 3. Install with hash enforcement, for example: ```bash python -m pip install --require-hashes -r requirements.lock ``` 4. Pin build dependencies as well as runtime dependencies. 5. Document and enforce the expected package index rather than inheriting arbitrary pip index configuration where operationally possible. 6. Review dependency updates through a controlled update process with automated tests and vulnerability scanning. 7. Avoid an unrestricted `--upgrade` path; require regeneration and review of the lock file before upgrades. 8. Provide a clean rebuild command so compromised or obsolete shared environments can be safely replaced. 9. Record resolved package versions after bootstrap for auditability. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill clearly requires shell execution, filesystem access, environment-variable access, and network communication to an external service, yet it declares no permissions or equivalent warning surface. This creates a transparency and policy-enforcement gap: users and host platforms may not realize the skill can read local content, write project files, and transmit data off-box to dLazy.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The overview explains that every slide image is generated through dLazy, but it does not clearly warn that user-provided documents, outlines, figures, screenshots, or other assets may be sent to an external service. In this context, the skill processes potentially sensitive business or research material, so omission of outbound-data disclosure can lead to unintentional exfiltration of confidential content.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The skill explicitly requires Chinese text output and repeatedly constrains slide text to formal Chinese, which can override a user's preferred language or system-level locale expectations. While not directly enabling code execution or data exfiltration, this can cause instruction-priority conflicts, reduce usability, and lead the agent to ignore user intent in multilingual contexts.

Session Persistence

Medium
Category
Rogue Agent
Content
The goal is to save a reusable visual system, not the current deck's private content.

User custom styles are saved to `${DLAZY_PPT_HOME:-~/.dlazy-ppt}/references/`, outside the skill install directory, so they survive skill updates and reinstalls. Never write user custom styles into the skill's own `references/` directory; that directory is reserved for built-in styles shipped with the skill.

## When To Use
Confidence
87% confidence
Finding
The skill explicitly instructs persistent storage of user-derived style files under `${DLAZY_PPT_HOME:-~/.dlazy-ppt}/references/`, outside the skill install directory so they survive updates and reinstalls. Even though the document warns against saving private content, persistent retention of user-derived artifacts increases privacy and data-governance risk if a style file accidentally captures sensitive visual cues, names, branding, or other residual information from user-supplied decks.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=1.0.2
Pillow>=10.0.0
requests>=2.32.0
filelock>=3.16.0
Confidence
98% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of different future versions and reduces build reproducibility. While not an exploit by itself, this weakens supply-chain control and can unexpectedly introduce vulnerable or incompatible releases over time.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=1.0.2
Pillow>=10.0.0
requests>=2.32.0
filelock>=3.16.0
Confidence
99% confidence
Finding
Pillow is declared with a minimum version only, so environments may resolve to different versions depending on installation time and index state. In image-processing workflows, this increases supply-chain risk because vulnerable or behavior-changing releases can be pulled in without review.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=1.0.2
Pillow>=10.0.0
requests>=2.32.0
filelock>=3.16.0
Confidence
98% confidence
Finding
Requests is unpinned, which makes dependency resolution non-deterministic and can introduce vulnerable upstream versions or regressions unexpectedly. Because this skill likely fetches remote content, controlling the exact HTTP client version is important for both security and reliability.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-pptx>=1.0.2
Pillow>=10.0.0
requests>=2.32.0
filelock>=3.16.0
Confidence
97% confidence
Finding
filelock is also specified as a floating minimum version, which weakens reproducibility and can bring in future releases with undiscovered issues. For libraries involved in filesystem locking, version drift can affect both security properties and race-condition behavior.

Known Vulnerable Dependency: Pillow==10.0.0 — 10 advisory(ies): CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2024-28219 (Pillow buffer overflow vulnerability); CVE-2026-55379 (Pillow `BdfFontFile`: `Image.new()` called without `_decompression_bomb_check()`) +7 more

Critical
Category
Supply Chain
Confidence
99% confidence
Finding
The requirements permit Pillow 10.0.0, and the finding indicates that version has multiple published advisories including severe memory-safety and possible code-execution issues. This skill explicitly processes images to generate slide decks, which makes the dependency especially exposed if it handles untrusted or externally sourced image inputs.

Known Vulnerable Dependency: requests==2.32.0 — 4 advisory(ies): CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs) +1 more

Medium
Category
Supply Chain
Confidence
95% confidence
Finding
The requirements allow requests 2.32.0, which the finding associates with known advisories such as credential leakage via malicious URLs. Since this skill may download articles, reports, or remote assets, a vulnerable HTTP client increases risk when handling attacker-controlled URLs or network content.

Known Vulnerable Dependency: filelock==3.16.0 — 4 advisory(ies): CVE-2026-22701 (filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLoc); CVE-2025-68146 (filelock has a TOCTOU race condition which allows symlink attacks during lock fi); CVE-2026-22701 (filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLoc) +1 more

Medium
Category
Supply Chain
Confidence
93% confidence
Finding
The requirements allow filelock 3.16.0, which is flagged for TOCTOU and symlink-related vulnerabilities. If this skill uses lock files in shared or attacker-influenced directories, an attacker may exploit filesystem races to overwrite or access unintended files.

Static analysis

No suspicious patterns detected.