Back to skill

Security audit

Skywork PPT

Security checks for vulnerabilities and agentic risk

Overview

This PowerPoint skill is mostly coherent, but it should be reviewed because it uploads local documents to cloud/public URLs and can modify local/system files without strong safeguards.

Install only if you are comfortable sending selected prompts and files to Skywork/cloud storage. Avoid confidential decks unless your organization approves that service, use a revocable API key stored in a protected secret store, do not echo the key in logs, run dependencies in a virtual environment, and use explicit output paths or backups for local slide edits.

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 (4)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:52
Finding
Unpinned Dependency Installation Into the System Python Environment<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:52-74` **Vulnerability Type**: Unsafe and unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash PYTHON_CMD="" for cmd in python3 python python3.13 python3.12 python3.11 python3.10 python3.9 python3.8; do if command -v "$cmd" &>/dev/null && "$cmd" -c "import sys; exit(0 if sys.version_info >= (3,8) else 1)" 2>/dev/null; then PYTHON_CMD="$cmd" break fi done if [ -z "$PYTHON_CMD" ]; then echo "ERROR: Python 3.8+ not found." echo "Install on macOS: brew install python3 or visit https://www.python.org/downloads/" exit 1 fi echo "Found Python: $PYTHON_CMD ($($PYTHON_CMD --version))" $PYTHON_CMD -m pip install -q --break-system-packages python-pptx echo "Dependencies ready." ``` The same general installation pattern also appears in `workflow_local.md:10`: ```bash pip install python-pptx ``` ### Technical Analysis The Skill instructs the Agent to install `python-pptx` without an exact version or package hash. Resolution therefore depends on the package index and dependency graph available when the Skill executes. A future compromised release, malicious mirror, altered pip configuration, or compromised transitive dependency could introduce executable code that was not present during this audit. The `--break-system-packages` option bypasses Python distribution protections and allows pip to modify an externally managed interpreter. This unnecessarily expands the impact beyond an isolated Skill environment and can overwrite or conflict with packages used by other applications. Installation is described as an environment check that should always run, meaning dependency mutation may occur even when the selected operation does not require a new installation. ### Attack Path 1. A user activates the Skill. 2. The Agent follows the mandatory environment-check instructions. 3. Pip resolves the unpinned package and transitive dependencies using t ...[truncated 993 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a dedicated virtual environment for the Skill instead of modifying the system interpreter. 2. Remove `--break-system-packages`. 3. Pin `python-pptx` and all transitive dependencies to reviewed versions. 4. Use a lock file with cryptographic hashes, such as a hash-locked requirements file: ```bash python3 -m venv .venv .venv/bin/python -m pip install \ --require-hashes \ -r requirements.lock ``` 5. Use an organization-approved package index and enforce TLS certificate validation. 6. Check whether the required dependency is already available before attempting installation. 7. Avoid automatic package installation for workflows that do not require `python-pptx`, such as remote web search or remote generation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/apikey-fetch.md:21
Finding
API Key Setup Instructions Expose and Persist Secrets in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `references/apikey-fetch.md:21-76` **Vulnerability Type**: Plaintext credential storage and secret disclosure through terminal output **Risk Level**: Medium ### Vulnerable Code ```json { "skills": { "entries": { "Skywork-ppt": { "enabled": true, "apiKey": "your_actual_skywork_api_key_here" } } } } ``` ```bash export SKYWORK_API_KEY="your_actual_skywork_api_key_here" ``` The instructions recommend persisting the preceding export command in `~/.zshrc` or `~/.bashrc`. ```json { "env": { "SKYWORK_API_KEY": "your_actual_skywork_api_key_here" } } ``` The verification procedure prints the complete credential: ```bash # Check that the environment variable is available echo "$SKYWORK_API_KEY" ``` ### Technical Analysis The guide recommends storing the API key directly in shell startup files or JSON configuration. It does not require restrictive file permissions or recommend a protected credential store. Shell initialization files and application configuration files are frequently included in backups, support bundles, workstation synchronization, or diagnostic collection. The verification command emits the complete API key to the terminal. In an Agent environment, terminal output may be retained in conversation transcripts, execution logs, CI output, shell recordings, monitoring systems, or screenshots. Although the runtime Python code does not log the key, the setup process creates an avoidable credential exposure path. ### Attack Path 1. A user follows the API-key setup guide. 2. The user stores the key in a shell startup file or plaintext JSON configuration. 3. The user runs `echo "$SKYWORK_API_KEY"` to verify the setup. 4. A local process, backup system, transcript collector, terminal logger, plugin, or another user with file access reads the key from configuration or captured output. 5. The attacker uses the exposed key to authenticate to Skywork as the ...[truncated 489 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer the platform's protected secret store or an operating-system keychain. 2. Do not recommend persistence in `.bashrc`, `.zshrc`, or general-purpose JSON settings unless no protected mechanism exists. 3. Require restrictive permissions for any unavoidable credential file: ```bash chmod 600 ~/.openclaw/openclaw.json chmod 600 ~/.claude/settings.json ``` 4. Replace full-secret verification with a presence check: ```bash if [ -n "${SKYWORK_API_KEY:-}" ]; then echo "SKYWORK_API_KEY is configured" else echo "SKYWORK_API_KEY is not configured" fi ``` 5. If a fingerprint is necessary, display only a small masked prefix or suffix. 6. Warn users not to paste keys into chats, logs, issue reports, screenshots, or command histories. 7. Document key rotation and immediate revocation procedures for suspected exposure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/web_search.py:55
Finding
Search Queries Can Escape the Temporary Directory Through Path Traversal<![CDATA[ ## Vulnerability Details **File Location**: `scripts/web_search.py:55-75` **Vulnerability Type**: User-controlled filename and unsafe temporary-file construction **Risk Level**: Medium ### Vulnerable Code ```python def main(): parser = argparse.ArgumentParser(description="Call local web_search API") parser.add_argument("queries", nargs="+", help="One or more search queries (max 3)") args = parser.parse_args() queries = args.queries[:3] out_dir = tempfile.mkdtemp(prefix="web_search_") api_key = get_skywork_api_key() if not api_key: print("[error] SKYWORK_API_KEY is required", file=sys.stderr) sys.exit(1) for i, q in enumerate(queries, 1): print(f"[query] {q} ...", file=sys.stderr, flush=True) raw = search(q, api_key) out_path = os.path.join(out_dir, f"{q}_result.txt") with open(out_path, "w", encoding="utf-8") as f: f.write(f"query: {q}\n\n{raw}") print(f'Already saved search result for query[{q}], \nout_path: {out_path}', flush=True) ``` ### Technical Analysis The query string is inserted directly into a filesystem path without sanitization. `os.path.join()` does not enforce containment within `out_dir`: - A query containing `../` can traverse to a parent directory. - If the formatted query path is absolute, `os.path.join()` discards `out_dir`. - Path separators and platform-specific path constructs are not rejected. - No resolved-path containment check is performed before opening the file. The file is opened in write mode, so an existing writable file at the resolved path can be truncated and replaced. The suffix `_result.txt` restricts which exact filenames can be targeted, but it does not prevent traversal or writes outside the temporary directory. ### Attack Path 1. An attacker supplies a presentation topic or other input that is carried into a search query containing path components such as `../../target`. 2. The Agent invokes `web_se ...[truncated 959 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not derive filenames from query contents. Use fixed index-based or random filenames: ```python out_path = os.path.join(out_dir, f"query_{i}_result.txt") ``` 2. Prefer `tempfile.NamedTemporaryFile()` or `tempfile.mkstemp()` for each result. 3. If descriptive names are required, permit only a narrow set of safe characters and impose a short length limit. 4. Resolve and verify containment before opening: ```python base = os.path.realpath(out_dir) candidate = os.path.realpath(os.path.join(base, safe_name)) if os.path.commonpath([base, candidate]) != base: raise ValueError("Output path escapes temporary directory") ``` 5. Reject absolute paths, `..` components, null bytes, and both POSIX and Windows path separators. 6. Create files using exclusive mode where overwriting is unnecessary. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/run_ppt_write.py:316
Finding
Backend-Provided Download URLs Are Fetched Without Destination or Size Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_ppt_write.py:316-332` **Vulnerability Type**: Unvalidated remote URL retrieval and unbounded response buffering **Risk Level**: Low The same pattern is present in `scripts/run_editable_convert.py:196-211`. ### Vulnerable Code From `scripts/run_ppt_write.py`: ```python elif event_type == "completionEvent": phase = data.get("phase", "") if phase == "done": download_url = data.get("download_url") write_log(log_file, "[PHASE] Generation complete, saving file to local disk. This may take 1 or 2 minutes, we are already success!") if not download_url: write_log(log_file, "[ERROR] No download_url in completionEvent") sys.exit(1) try: req2 = urllib.request.Request(download_url, method="GET") with urllib.request.urlopen(req2, timeout=120) as r: with open(out_abs, "wb") as f: f.write(r.read()) write_log(log_file, f"[DONE] saved={out_abs} download_url={download_url}") except Exception as e: write_log(log_file, f"[ERROR] Download failed: {e}") sys.exit(1) ``` Equivalent logic from `scripts/run_editable_convert.py`: ```python if not download_url: write_log(log_file, "[ERROR] No download_url in completionEvent") sys.exit(1) try: req2 = urllib.request.Request(download_url, method="GET") with urllib.request.urlopen(req2, timeout=120) as r: with open(out_abs, "wb") as f: f.write(r.read()) write_log(log_file, f"[DONE] saved={out_abs} download_url={download_url}") except Exception as e: write_log(log_file, f"[ERROR] Download failed: {e}") sys.exit(1) ``` ### Technical Analysis The URL originates from an SSE response supplied by the remote backend and is passed directly to `urllib.request.urlopen()`. The scripts do not: - Require an HTTPS URL. - Restrict downloads to an approved Skywork/CDN hostn ...[truncated 2010 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require `https` and allowlist the expected Skywork CDN hostnames. 2. Resolve hostnames and reject loopback, private, link-local, multicast, and otherwise non-public addresses. 3. Disable automatic redirects or validate every redirect target against the same policy. 4. Stream the response in bounded chunks instead of calling `r.read()` without a limit: ```python max_bytes = 100 * 1024 * 1024 total = 0 with open(temp_output, "xb") as f: while True: chunk = r.read(1024 * 1024) if not chunk: break total += len(chunk) if total > max_bytes: raise ValueError("Download exceeds size limit") f.write(chunk) ``` 5. Check `Content-Length` when available, while still enforcing the streamed limit. 6. Validate the response MIME type and verify that the result is a valid PPTX ZIP package before replacing the destination. 7. Download to a securely created temporary file and atomically rename it after successful validation. 8. Redact query strings or signed tokens before logging the download URL. 9. Apply the same controls in both `run_ppt_write.py` and `run_editable_convert.py`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill mandates web search to gather topic material, which is broader than basic presentation manipulation and introduces outbound network requests based on user prompts. While this may support content generation, it materially expands the skill’s behavior and data exposure beyond what a local PPT tool description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill mandates web search to gather topic material, which is broader than basic presentation manipulation and introduces outbound network requests based on user prompts. While this may support content generation, it materially expands the skill’s behavior and data exposure beyond what a local PPT tool description suggests.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill mandates web search to gather topic material, which is broader than basic presentation manipulation and introduces outbound network requests based on user prompts. While this may support content generation, it materially expands the skill’s behavior and data exposure beyond what a local PPT tool description suggests.

Self-Modification

High
Category
Rogue Agent
Content
primaryEnv: SKYWORK_API_KEY
---

# PPT Write Skill

Five capabilities: **generate**, **template imitation**, **edit existing PPT**, **convert NotebookLM export to editable PPTX**, and **local file operations**.
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Agent Config Directory Access

High
Category
Agent Snooping
Content
**Option B — Claude Code settings**

Add the variable to `~/.claude/settings.json`:

```json
{
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
**Option B — Claude Code settings**

Add the variable to `~/.claude/settings.json`:

```json
{
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Agent Config Directory Access

High
Category
Agent Snooping
Content
**Option B — Claude Code settings**

Add the variable to `~/.claude/settings.json`:

```json
{
Confidence
90% confidence
Finding
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Self-Modification

High
Category
Rogue Agent
Content
# ---------------------------------------------------------------------------

def _resolve_output(args, original_file: str) -> str:
    """Use -o output path if specified by the user, otherwise overwrite the original file."""
    if hasattr(args, "output") and args.output:
        return args.output
    return original_file
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The script’s documented purpose is generic file parsing and OCR/text extraction for arbitrary reference files, which materially exceeds the stated PPT-focused skill scope. Scope expansion is security-relevant because it enables users or downstream automation to upload non-PPT documents to a remote service, increasing the chance of unintended sensitive data handling and creating capability creep beyond what the skill description justifies.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
This script adds a general web-search and network retrieval capability inside a skill advertised as PPT creation/editing. That mismatch materially expands the skill's attack surface: it can send arbitrary user-controlled queries to a remote endpoint and ingest untrusted remote content, which may then be reused elsewhere in the agent workflow. In the PPT-focused context, the capability is unjustified and increases the risk of covert data exfiltration, prompt-injection via retrieved content, or unauthorized network access.

Missing User Warnings

High
Confidence
97% confidence
Finding
The workflow explicitly requires uploading a local PPTX to a publicly accessible OSS/CDN URL before editing, but it does not require user consent, warn about public accessibility, or limit exposure duration. Because PPTX files often contain sensitive business content, speaker notes, embedded media, or internal branding, this can cause unintended data disclosure simply by following the workflow as written.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The optional parsing step sends arbitrary additional local files such as PDF, DOCX, PPTX, and images to a remote document parse service. This materially broadens the skill from presentation work into generalized remote ingestion of user documents, creating a strong risk of confidential data exposure if users do not understand that their local source files are being transmitted off-device.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The workflow uploads a user-provided local template PPTX to an external OSS/CDN service without an explicit consent gate or clear necessity stated to the user. Template files can contain sensitive business content, speaker notes, embedded media, comments, authorship metadata, or confidential branding assets, so silent exfiltration to third-party storage creates a real confidentiality risk.

Self-Modification

High
Category
Rogue Agent
Content
# Delete slide 3
$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3

# Delete slides 3, 5, 7-9, overwrite the original file
$PYTHON_CMD scripts/local_pptx_ops.py delete --file my.pptx --slides 3,5,7-9

# Save to a new file after deletion (don't overwrite the original)
Confidence
95% confidence
Finding
The documented default behavior allows overwriting the original PPTX during slide deletion, which is a direct destructive self-modification of user data. In a tool routed by natural-language commands, this increases the chance that a misunderstood or overly broad request permanently alters the only copy of a file.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill declares broad capabilities that include environment access, local file read/write, and network operations, but it does not declare any explicit tool scope or allowed-tools boundary. In a skill that uploads local files and sends user prompts to a remote service, the absence of clear permission constraints increases the risk of unintended data access or overbroad tool use by the agent.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The instruction to perform web searches expands the skill from document manipulation into external content acquisition, which changes its trust and privacy profile. This is dangerous because user topics, prompts, or associated context may be sent to third-party search services without the manifest making that expansion sufficiently explicit.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The edit workflow hard-codes `--language Chinese` in the command example, which directs the skill to use a specific language regardless of the user's preference. This is a natural-language policy issue because the file elsewhere serves multilingual users, but this step does not offer language choice or justify the restriction.

Session Persistence

Medium
Category
Rogue Agent
Content
- Log in with your Skywork account
- Open account / Settings / API Key (**https://skywork.ai/?openApiKeySetting=1**)
- Create or copy your **API key**

If your organization uses a separate console or test environment, use the URL and credentials your team provides.
Confidence
79% confidence
Finding
The instruction to create or copy an API key encourages handling a persistent credential, and the overall guide then stores it in plaintext config or shell initialization files. While normal for setup docs, this increases the risk of long-lived secret exposure if the machine, home directory, or dotfiles are accessible to others.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The guide tells users to export, store, and echo a live API key but does not warn that the key is a sensitive credential or discuss risks like terminal history exposure, shoulder-surfing, checked-in config files, or shared home-directory files. This can lead to credential disclosure and unauthorized use of the Skywork account if the key is copied into insecure locations or printed in logs.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The helper defaults to overwriting the input PPTX when no output path is supplied, and destructive commands like delete/reorder call it without any confirmation or backup. In an agent context, a mistaken invocation, ambiguous user request, or prompt-manipulated action can permanently destroy or alter the only local copy of a presentation.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The code uploads a user-provided file to a server-side endpoint that performs generic analysis, OCR, and text extraction, not just presentation editing. In a PPT skill, this broader remote document-processing behavior makes the feature more dangerous because users may reasonably assume local slide operations while the code can exfiltrate the contents of arbitrary documents for server-side inspection.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script reads the entire local file and sends it to a remote API endpoint with authorization headers, but it provides no explicit warning or consent checkpoint that the file contents will leave the local environment. This is dangerous because users may upload confidential presentations or embedded documents under the impression that the operation is purely local, leading to unintended disclosure of sensitive data.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The CLI argument sets `--language` to `en` by default, which imposes a specific language preference unless the caller explicitly overrides it. This is a natural-language policy concern because the skill defaults to one locale rather than offering a neutral choice or prompting for user preference.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The script reads arbitrary local file content via --reference-file and forwards it as reference text to the remote service, which can cause unintended exfiltration of sensitive local data. Because the file path is unconstrained and the feature is broader than strictly necessary for PPT manipulation, it expands the skill's data access beyond user expectations.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The script sends user-provided content and metadata to a remote Skywork API and then downloads the resulting PPTX from a URL supplied by that service. In a skill framed around PowerPoint operations, this is security-relevant because local content may leave the host and remote fetching of the final file introduces trust and data-boundary concerns that should be explicitly disclosed and constrained.

Static analysis

No suspicious patterns detected.