Back to skill

Security audit

draw-animal

Security checks for vulnerabilities and agentic risk

Overview

The skill is a simple local animal-description generator, but its instructions pass user-controlled text into a shell command without quoting, which could become command execution in some runners.

Review this skill before installing. It appears to be a small local text generator with no network or persistence behavior, but its invocation should be changed to pass arguments safely without a shell, or quote and validate all user-controlled values before execution.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:39
Finding

Shell Command Injection Through Unquoted User-Controlled Parameters

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, line 39
Vulnerability Type: Shell command injection
Risk Level: High

Vulnerable Code:

bash
python3 {baseDir}/scripts/draw_animal.py --animal {animal:-pig} --lang {lang:-en}

Technical Analysis

The Skill instructs the Agent to insert the user-derived animal and lang parameters directly into a shell command without shell-safe quoting or a structured argument-array invocation. If the execution environment performs textual interpolation and passes the resulting command to a shell, shell metacharacters in either parameter can terminate or alter the intended command and introduce additional commands.

The validation in scripts/draw_animal.py does not mitigate this issue. Shell parsing and command substitution occur before the Python process receives and validates its arguments. Consequently, the substring denylist in validate_animal() cannot inspect or block commands that the shell has already interpreted. The lang argument also has no protection before shell parsing; its argparse choices are enforced only after Python starts.

Exploitability depends on whether the host executes the documented command through a shell using direct placeholder interpolation. Under that execution model, the flaw crosses the boundary from harmless text generation to arbitrary command execution.

Attack Path

  1. An attacker submits an animal or language value containing shell control syntax.
  2. The Agent extracts the attacker-controlled value as the animal or lang parameter.
  3. The value is interpolated into the command shown in SKILL.md without shell-safe encoding.
  4. The host shell parses the injected metacharacters before launching draw_animal.py.
  5. The shell executes attacker-selected commands under the account and permissions of the Agent or Skill runner.
  6. Python-side validation either runs only on the remaining arguments or is never reached, so ...[truncated 980 chars]
Remediation
View remediation

Remediation Suggestions

  • Invoke the script through a process API that accepts a structured argument array rather than constructing a shell command. For example, pass arguments equivalent to:
    text
    ["python3", "{baseDir}/scripts/draw_animal.py", "--animal", animal, "--lang", lang]
    
  • Disable shell execution for this invocation. In Python-based launchers, use subprocess.run([...], shell=False, check=True) or an equivalent API.
  • Validate parameters before process creation. Allowlist the supported animal names and restrict lang to en or zh.
  • If unknown animal names must remain supported, apply a strict character and length policy, such as letters, spaces, and hyphens only, rather than relying on a restricted-word substring denylist.
  • If shell use is unavoidable, apply platform-appropriate shell escaping to every dynamic argument. Quoting is defense in depth and should not replace structured invocation and allowlist validation.
  • Retain argparse validation inside the script as a secondary control, but do not treat post-shell validation as protection against command injection.
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose implies describing an actual animal picture, which would require accepting or analyzing image input. The code does not access files, images, or any vision/model capability. Instead, it takes a user-supplied animal name, picks random predefined traits, environment, and action, and prints a templated description in English or Chinese. That is a materially different primary behavior from picture description, so this is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The CLI enforces choices=['en', 'zh'], which hard-limits the skill to two languages. Under the policy, locale constraints can be a concern when a skill forces specific languages without broader user opt-in or justification, and this file does not document why only these locales are allowed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.