Back to skill

Security audit

Cat Selfie

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but its configurable prompts can be executed through a shell, creating a real local command-injection risk.

Review this skill before installing. Do not use custom scene prompts from untrusted sources unless the shell invocation is fixed to use argument-array execution such as execFileSync or spawnSync. If you enable heartbeat sending, add explicit confirmation or rate limits and make sure the shared images directory cannot cause unintended images to be sent.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/selfie.js:69
Finding
Shell Command Injection Through Configurable Scene Prompts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/selfie.js`, lines 69-78 **Vulnerability Type**: OS command injection through shell-based process execution **Risk Level**: High ### Vulnerable Code ```javascript // 调用图像生成脚本 const prompt = selectedScene.prompt; const command = `python3 "${IMAGE_GENERATE_SCRIPT}" "${prompt}"`; console.log(`⏳ 生成中...(这可能需要几秒钟)`); execSync(command, { stdio: 'inherit', cwd: path.dirname(IMAGE_GENERATE_SCRIPT) }); ``` ### Technical Analysis The scene prompt is read from `config/scenes.json` and interpolated directly into a command string passed to `child_process.execSync()`. This API executes the supplied string through a system shell. Wrapping `prompt` in double quotes does not make it safe. A prompt containing a double quote can terminate the intended argument and append shell metacharacters or additional commands. The documentation explicitly supports adding custom scenes and prompts, so the configuration is an expected input surface rather than an immutable internal constant. For example, a prompt equivalent to the following could escape the quoted argument: ```text "; touch /tmp/cat-selfie-command-injection; # ``` This would produce a shell command structurally equivalent to: ```bash python3 "/path/to/image_generate.py" ""; touch /tmp/cat-selfie-command-injection; #" ``` The injected command would execute with the same operating-system identity and environment as the Node.js process. ### Attack Path 1. An attacker modifies `config/scenes.json`, distributes a malicious custom scene, or persuades a user to add an attacker-controlled prompt. 2. The malicious prompt includes a quote followed by shell syntax. 3. The user invokes `selfie.js` with the malicious scene ID or allows it to be selected randomly. 4. `generateSelfie()` reads the malicious prompt from the scene configuration. 5. The prompt is interpolated into the `command` string without shell escaping. 6. `execSync()` passes the command to th ...[truncated 666 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Avoid invoking a shell. Pass the executable and its arguments separately with `execFileSync()` or `spawnSync()`: ```javascript const { execFileSync } = require('child_process'); execFileSync( 'python3', [IMAGE_GENERATE_SCRIPT, prompt], { stdio: 'inherit', cwd: path.dirname(IMAGE_GENERATE_SCRIPT) } ); ``` Additional hardening measures should include: 1. Validate that every scene has string-valued `id`, `name`, `emoji`, and `prompt` properties. 2. Impose a reasonable maximum prompt length to prevent resource abuse. 3. Reject control characters if they are not required by the image-generation interface. 4. Keep `shell: false` if the implementation is changed to `spawnSync()`. 5. Restrict write access to the Skill configuration so untrusted local processes cannot silently replace scene prompts. 6. Add a regression test containing quotes and shell metacharacters and verify that they are delivered only as a single Python argument. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/selfie.js:81
Finding
Untrusted Image Selection From a Shared Output Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/selfie.js`, lines 81-101 **Vulnerability Type**: Output substitution and race condition in shared storage **Risk Level**: Medium ### Vulnerable Code ```javascript // 查找最新生成的图片 const files = fs.readdirSync(OUTPUT_DIR) .filter(f => f.endsWith('.png') || f.endsWith('.jpg')) .map(f => ({ name: f, path: path.join(OUTPUT_DIR, f), mtime: fs.statSync(path.join(OUTPUT_DIR, f)).mtime })) .sort((a, b) => b.mtime - a.mtime); if (files.length === 0) { return { success: false, message: '❌ 图片生成失败,未找到生成的文件' }; } const latestImage = files[0]; console.log(`✅ 自拍生成成功!`); console.log(`📁 保存位置:${latestImage.path}`); ``` ### Technical Analysis The Skill does not obtain or verify the exact output path produced by the current image-generation process. After the subprocess exits, it scans a shared directory and assumes that the file with the newest modification timestamp is the result of the current request. That assumption is unsafe when another process or concurrent Skill invocation can write to `~/.openclaw/workspace/images`. A different PNG or JPG can become the newest entry between generation and directory scanning. The code performs no request correlation, filename validation, creation-time boundary check, ownership verification, or content verification. Because the documented workflow recommends sending the returned image through a messaging tool, selecting an unrelated image can cross a trust boundary and cause unintended content to be transmitted. ### Attack Path 1. The attacker or another concurrent process has write access to the shared images directory. 2. A legitimate user starts selfie generation. 3. During or immediately after image generation, the other process creates or updates a PNG or JPG in that directory. 4. The injected or unrelated file receives the newest modification timestamp. 5. The Skill sorts all matching files by modifica ...[truncated 842 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Bind each invocation to an explicit, unique output path rather than scanning a shared directory: 1. Generate a cryptographically random request identifier with `crypto.randomUUID()`. 2. Create a private per-request directory using `fs.mkdtempSync()` and restrictive permissions. 3. Pass the exact destination path to the Python generator. 4. Require the generator to return or create that exact path. 5. Verify that the resulting path remains inside the intended request directory by resolving and comparing canonical paths. 6. Verify that the file was created successfully and is a regular file. 7. Where appropriate, validate the image signature rather than relying only on its extension. 8. Remove temporary request directories after downstream processing. If the external generator cannot accept an output path, capture its structured output and parse the exact generated filename. At minimum, record the invocation start time and only accept a uniquely named file created after that point, although this remains weaker than an explicit per-request output path. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The skill description, instructions, examples, and output documentation are entirely in Chinese, which imposes a specific language on users. The file does not offer an alternative language, opt-in, or explain that the skill is intentionally region- or language-specific.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation instructs integrating the skill into a heartbeat mechanism that automatically generates images and then sends them via a messaging tool, but it does not clearly warn users that this triggers external network calls to a third-party image API and may transmit generated content onward. In an agent/automation context, silent external API use and auto-sending behavior can surprise operators, create privacy/compliance issues, and enable unintended data egress or cost-incurring actions.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This JSON manifest contains multiple user-facing natural-language fields such as scene names, prompts, and a note, all exclusively in Chinese. Under the policy, forcing a specific language without offering choice or documenting a justified locale constraint is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file's user-facing description and operational messaging are written entirely in Chinese, indicating a fixed language choice with no sign of user selection or opt-in. The stated policy for this audit flags language or locale constraints when the skill forces a specific language without offering choice.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The script builds a shell command string and executes it with execSync, passing prompt text derived from a JSON config into the command line. Because shell metacharacters inside the prompt can break out of the quoted argument, a modified or malicious scenes.json entry could trigger arbitrary command execution under the current user account.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The natural-language instructions and usage guidance are entirely in Chinese, which can impose a fixed language/locale on users without opt-in. The file does not mention that the skill is intended only for Chinese-speaking users or provide an alternative language option.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The natural-language description is entirely in Chinese and presents the skill as Chinese-only, with no indication that users may choose another language or that the locale restriction is required for a region-specific purpose. This can violate organizational language/locale policy when skills are expected to avoid forcing a specific language without opt-in.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/selfie.js:75