Back to skill

Security audit

批量图像处理工具

Security checks for vulnerabilities and agentic risk

Overview

This image-processing skill has a coherent purpose, but its executable wrappers build shell commands from unvalidated user input, creating a real arbitrary-command-execution risk.

Install only after the wrappers are hardened to avoid shell execution, validate numeric options, restrict input and output paths, and define non-overwrite behavior. Until then, do not process untrusted filenames or parameters; use a disposable workspace, explicit output directories, backups, and pinned installer versions.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/rotate.js:25
Finding
OS Command Injection in Image Rotation Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/rotate.js:25-43` **Vulnerability Type**: OS command injection through shell-string construction **Risk Level**: High ### Vulnerable Code ```js const args = parseArgs(process.argv.slice(2)); const input = args.input; const output = args.output || input.replace('.', '_rotated.'); const angle = args.angle || '0'; const scale = args.scale || '1.0'; if (!input) { console.error('Error: --input is required'); console.error('Usage: node rotate.js --input photo.jpg --output rotated.jpg --angle 90'); process.exit(1); } try { console.log(`🔄 Rotating image: ${input}`); console.log(` Angle: ${angle}°, Scale: ${scale}`); const cmd = `cli-anything-imutils rotate-cmd "${input}" "${output}" --angle ${angle} --scale ${scale}`; const result = execSync(cmd, { encoding: 'utf-8' }); ``` ### Technical Analysis The `input`, `output`, `angle`, and `scale` values originate from command-line arguments and are inserted into a command string passed to `child_process.execSync`. Because `execSync` executes the string through a system shell, shell operators embedded in an argument can be interpreted as command syntax. The `angle` and `scale` values are especially exposed because they are inserted without quoting or numeric validation. Quoting `input` and `output` is not an adequate defense because embedded quotation marks and shell metacharacters are neither rejected nor safely escaped. ### Attack Path 1. An attacker influences the arguments supplied to `scripts/rotate.js`, directly or through an Agent-generated invocation. 2. The attacker places shell syntax in `--angle`, `--scale`, `--input`, or `--output`. 3. `parseArgs` stores the value without validation. 4. The value is concatenated into `cmd`. 5. `execSync` passes the constructed string to the operating-system shell. 6. The shell interprets the injected syntax and executes an additional command with the privileges of the Node.js pr ...[truncated 524 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Avoid invoking a shell. Use `execFileSync` or `spawnSync` with a fixed executable and an argument array: ```js const { execFileSync } = require('child_process'); const parsedAngle = Number(angle); const parsedScale = Number(scale); if (!Number.isFinite(parsedAngle)) { throw new Error('Angle must be a finite number'); } if (!Number.isFinite(parsedScale) || parsedScale <= 0) { throw new Error('Scale must be a positive finite number'); } const result = execFileSync( 'cli-anything-imutils', [ 'rotate-cmd', input, output, '--angle', String(parsedAngle), '--scale', String(parsedScale) ], { encoding: 'utf-8', shell: false } ); ``` Additional hardening should include: - Validate `input` before deriving the default output path. - Reject missing option values and unexpected arguments. - Apply reasonable numeric ranges to angle and scale. - Verify that input and output paths comply with the intended filesystem policy. - Run image-processing operations with the minimum required operating-system permissions. - Add tests using spaces, quotation marks, and shell metacharacters to confirm that arguments are handled only as data. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/resize.js:24
Finding
OS Command Injection in Image Resize Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/resize.js:24-52` **Vulnerability Type**: OS command injection through shell-string construction **Risk Level**: High ### Vulnerable Code ```js const args = parseArgs(process.argv.slice(2)); const input = args.input; const output = args.output || input.replace('.', '_resized.'); const width = args.width || '0'; const height = args.height || '0'; const interpolation = args.interpolation || 'area'; if (!input) { console.error('Error: --input is required'); console.error('Usage: node resize.js --input photo.jpg --output small.jpg --width 800 --height 600'); process.exit(1); } if (width === '0' && height === '0') { console.error('Error: Must specify --width or --height'); process.exit(1); } try { console.log(`📏 Resizing image: ${input}`); console.log(` Target: ${width}x${height}, Interpolation: ${interpolation}`); let cmd = `cli-anything-imutils resize "${input}" "${output}"`; if (width !== '0') cmd += ` --width ${width}`; if (height !== '0') cmd += ` --height ${height}`; cmd += ` --inter ${interpolation}`; const result = execSync(cmd, { encoding: 'utf-8' }); ``` ### Technical Analysis All resize parameters are derived from untrusted command-line input. They are concatenated into a single shell command and executed using `execSync`. The `width`, `height`, and `interpolation` values are unquoted and unvalidated, creating a direct shell-injection primitive. The documented interpolation options are not enforced by the implementation. Although `input` and `output` are surrounded by quotation marks, crafted values can terminate the quoted context because embedded quotation marks are not escaped. Checking only whether width and height equal the string `"0"` does not establish that either value is numeric, positive, finite, or free of command syntax. ### Attack Path 1. An attacker controls or influences a resize request. 2. The attacker supplies ...[truncated 823 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Replace shell execution with argument-array execution and validate every option: ```js const { execFileSync } = require('child_process'); const validInterpolations = new Set([ 'nearest', 'bilinear', 'cubic', 'area', 'lanczos' ]); const parsedWidth = Number(width); const parsedHeight = Number(height); if (!Number.isInteger(parsedWidth) || parsedWidth < 0) { throw new Error('Width must be a non-negative integer'); } if (!Number.isInteger(parsedHeight) || parsedHeight < 0) { throw new Error('Height must be a non-negative integer'); } if (parsedWidth === 0 && parsedHeight === 0) { throw new Error('Width or height must be greater than zero'); } if (!validInterpolations.has(interpolation)) { throw new Error('Unsupported interpolation method'); } const commandArgs = ['resize', input, output]; if (parsedWidth !== 0) commandArgs.push('--width', String(parsedWidth)); if (parsedHeight !== 0) commandArgs.push('--height', String(parsedHeight)); commandArgs.push('--inter', interpolation); const result = execFileSync( 'cli-anything-imutils', commandArgs, { encoding: 'utf-8', shell: false } ); ``` Also: - Validate `input` before calculating a default output name. - Enforce sensible maximum image dimensions to reduce resource-exhaustion risk. - Reject duplicate, malformed, and valueless options. - Restrict filesystem paths when the caller should only access a designated workspace. - Add regression tests proving that shell metacharacters are passed as literal argument content rather than interpreted. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/translate.js:24
Finding
OS Command Injection in Image Translation Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/translate.js:24-42` **Vulnerability Type**: OS command injection through shell-string construction **Risk Level**: High ### Vulnerable Code ```js const args = parseArgs(process.argv.slice(2)); const input = args.input; const output = args.output || input.replace('.', '_shifted.'); const x = args.x || '0'; const y = args.y || '0'; if (!input) { console.error('Error: --input is required'); console.error('Usage: node translate.js --input photo.jpg --output shifted.jpg --x 50 --y 30'); process.exit(1); } try { console.log(`↔️ Translating image: ${input}`); console.log(` Shift: X=${x}, Y=${y}`); const cmd = `cli-anything-imutils translate-cmd "${input}" "${output}" --x ${x} --y ${y}`; const result = execSync(cmd, { encoding: 'utf-8' }); ``` ### Technical Analysis The script inserts untrusted `input`, `output`, `x`, and `y` values into a command string passed to `execSync`. The `x` and `y` arguments are not quoted and are not parsed as numbers. Consequently, shell operators in either value are interpreted by the shell rather than passed exclusively to `cli-anything-imutils`. The quoted path arguments are also unsafe because the script does not escape embedded quotation marks or shell-specific expansion syntax. This means command injection is possible through both numeric options and filenames. ### Attack Path 1. An attacker causes the Skill to invoke the translation wrapper with attacker-controlled arguments. 2. Shell syntax is embedded in an `--x`, `--y`, `--input`, or `--output` value. 3. The custom parser accepts the value as an unrestricted string. 4. Template interpolation places the value into `cmd`. 5. `execSync` evaluates the resulting command through a shell. 6. The attacker's additional command runs under the invoking user's security context. ### Impact Assessment An attacker can execute arbitrary local commands with the privileges of the Node.js proc ...[truncated 385 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Execute the fixed program directly and validate translation offsets: ```js const { execFileSync } = require('child_process'); const parsedX = Number(x); const parsedY = Number(y); if (!Number.isInteger(parsedX) || !Number.isInteger(parsedY)) { throw new Error('Translation offsets must be integers'); } const result = execFileSync( 'cli-anything-imutils', [ 'translate-cmd', input, output, '--x', String(parsedX), '--y', String(parsedY) ], { encoding: 'utf-8', shell: false } ); ``` Further hardening: - Enforce reasonable minimum and maximum offsets. - Validate the input before constructing the default output path. - Reject missing values, unknown options, and malformed argument sequences. - Constrain input and output paths to an approved workspace where appropriate. - Do not attempt to solve this issue with manual shell escaping; avoiding the shell is the more reliable control. - Add cross-platform security tests because shell parsing differs between Windows and Unix-like systems. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skeleton.js:24
Finding
OS Command Injection in Image Skeletonization Wrapper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skeleton.js:24-39` **Vulnerability Type**: OS command injection through unsafe path interpolation **Risk Level**: High ### Vulnerable Code ```js const args = parseArgs(process.argv.slice(2)); const input = args.input; const output = args.output || input.replace('.', '_skeleton.'); if (!input) { console.error('Error: --input is required'); console.error('Usage: node skeleton.js --input photo.jpg --output skeleton.jpg'); process.exit(1); } try { console.log(`🦴 Skeletonizing image: ${input}`); const cmd = `cli-anything-imutils skeleton "${input}" "${output}"`; const result = execSync(cmd, { encoding: 'utf-8' }); ``` ### Technical Analysis The input and output paths are attacker-controllable strings embedded into a shell command. Surrounding them with double quotation marks does not make the operation safe: a path containing an embedded quotation mark can terminate the quoted argument, after which shell operators can introduce another command. Shell-dependent expansion behavior may create additional risks even without terminating the quoted string. Because `execSync` receives a command string rather than an executable plus discrete arguments, the shell parses attacker-controlled path content as possible syntax. ### Attack Path 1. An attacker supplies or causes processing of a crafted input or output path. 2. The crafted path contains content that exits the quoted argument and introduces shell syntax. 3. `parseArgs` stores the complete value without validation. 4. The path is interpolated into the `cmd` string. 5. `execSync` invokes the command through the system shell. 6. The injected command executes with the permissions of the Skill process. ### Impact Assessment Exploitation enables arbitrary command execution in the invoking user's context. The attacker could access or change files available to that user, inspect process secrets, launch additional executables, ...[truncated 243 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Pass paths as discrete process arguments without invoking a shell: ```js const { execFileSync } = require('child_process'); const result = execFileSync( 'cli-anything-imutils', ['skeleton', input, output], { encoding: 'utf-8', shell: false } ); ``` Additional controls should include: - Check `input` before deriving the default output path. - Validate that the input exists, is a regular file, and has an accepted image type. - Apply a filesystem access policy to prevent unintended reads or writes outside the approved workspace. - Define overwrite behavior explicitly and avoid replacing existing files unless authorized. - Reject malformed or missing command-line values. - Add regression tests with spaces, quotation marks, and shell metacharacters in filenames to verify that they are treated only as path data. - Run the wrapper under a least-privileged account. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
Most instructional content, examples, and the "对 AI 这样说" section are presented only in Chinese, with no indication that other languages are supported or that Chinese is a justified locale constraint. This can violate a language/locale policy when a skill effectively requires one language without user opt-in.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README advertises bulk image processing and output generation but does not clearly warn that files may be created, overwritten, or modified at scale. In a skill context, missing disclosure around write behavior can lead to destructive or unexpected filesystem changes, especially during batch operations on large photo sets.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The README instructs users to run `npx skills add` without pinning a specific version or commit, which can cause installation of whatever package/version is current at execution time. This creates a supply-chain risk because a compromised or changed upstream package could alter behavior or execute unintended code during installation.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The local installation example still uses `npx skills add` without pinning the `skills` tool version, so the same supply-chain exposure remains even if the skill path is local. An unpinned installer can change over time or be replaced upstream, leading to unexpected code execution in the user's environment.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The example trigger phrases are broad natural-language requests such as 'batch process these images' and 'rotate all product images 90 degrees,' which can overlap with ordinary user instructions. In an agent environment, this increases the chance of accidental skill invocation and unintended file operations without the user explicitly selecting the skill.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The batch workflow examples create directories, write output files, and explicitly delete temporary files (`Remove-Item $temp`) without a prominent warning about overwrite and deletion behavior. In an agent-driven context, users may authorize broad file operations without realizing the examples can clobber existing outputs or remove files matching unexpected names, leading to data loss or destructive actions in the wrong directory.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
The natural-language instructions, examples, and invocation phrases are entirely in Chinese, including the suggested user prompts, which can impose a language-specific usage pattern without opt-in. Under SQP-3, forcing a specific language or locale without user choice is a policy concern unless the constraint is explicitly documented and justified.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/resize.js:52

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/rotate.js:43

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/skeleton.js:39

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/translate.js:42