T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:72
- Finding
- Shell Command Injection Through Unquoted User-Controlled Arguments## Vulnerability Details **File Location**: `SKILL.md:72-89` **Vulnerability Type**: OS command injection **Risk Level**: High The skill documentation instructs the agent to interpolate user-controlled values directly into shell command templates: ```bash node ~/.claude/skills/payment/scripts/payment_api.js \ --amount {amount} \ [--order_type {order_type}] \ [--payee {payee}] \ [--description {description}] ``` ```bash python3 ~/.claude/skills/payment/scripts/payment_api.py \ --amount {amount} \ [--order_type {order_type}] \ [--payee {payee}] \ [--description {description}] ``` ### Technical Analysis The `amount`, `order_type`, `payee`, and `description` values originate from users or calling skills. The documented commands do not quote, escape, or validate these values before inserting them into a command interpreted by a shell. If an agent follows this construction literally through a shell, shell metacharacters contained in an argument can terminate or alter the intended command and introduce additional commands. The vulnerability exists before either payment script processes its arguments, so the scripts' argument parsers cannot prevent exploitation. This is particularly dangerous for free-form fields such as `payee` and `description`, which can plausibly contain spaces and punctuation and have no documented character restrictions. ### Attack Path 1. An attacker triggers the payment skill directly or through another skill. 2. The attacker supplies a crafted `description`, `payee`, or amount containing a shell command separator or command substitution. 3. The agent replaces the corresponding placeholder in the documented command template. 4. The resulting command is passed to a shell. 5. The shell interprets the metacharacters and executes the injected command in addition to, or instead of, the payment script. 6. The injected process inherits the operating-system permissions an ...[truncated 704 chars]
- Remediation
- ## Remediation Suggestions - Do not construct commands by interpolating values into shell strings. - Invoke Node.js or Python through an execution API that accepts an argument array and explicitly disables shell interpretation. - Pass each value as an independent argument, for example conceptually as `["script.js", "--amount", amount, "--description", description]`. - Require the amount to match a strict decimal format and enforce positive-value, precision, and upper-bound rules before execution. - Apply explicit length and character restrictions to `order_type`, `payee`, and `description`. - If shell execution is unavoidable, use a platform-appropriate escaping function for every dynamic value; argument-array execution should still be preferred. - Add tests using spaces, quotes, command separators, substitutions, newlines, and leading dashes to verify that supplied values cannot change command structure.
