T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:85
- Finding
- Shell Command Injection Through Unsafe Diagram-Code Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:85-89` **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code Snippet ```bash python scripts/generate_drawio_url.py -t mermaid -c "graph TD\n A --> B" python scripts/generate_drawio_url.py --type xml --code "<mxGraphModel>...</mxGraphModel>" python scripts/generate_drawio_url.py -t csv -c "name,manager\nCEO,\nCTO,CEO" ``` ### Technical Analysis The Skill instructs an agent to pass generated Mermaid, XML, or CSV content directly through a double-quoted shell argument. Diagram content may be based on untrusted user input and can contain shell metacharacters such as double quotes, backticks, or `$()` command substitutions. Double quotes do not prevent shell command substitution. If an agent constructs and executes the documented command through a shell, attacker-controlled content can terminate or alter the intended argument or cause the shell to evaluate embedded substitutions before `generate_drawio_url.py` receives the diagram code. For example, an attacker could request a Mermaid node containing content similar to: ```text A["$(id > /tmp/drawio-injection-result)"] ``` If this content is interpolated into the documented command template, the shell may execute `id > /tmp/drawio-injection-result`. The Python script itself does not invoke a subprocess; the vulnerability arises from the unsafe shell invocation pattern prescribed by the Skill documentation. ### Attack Path 1. An attacker asks the agent to create a diagram containing shell command-substitution syntax in a label, XML attribute, or CSV field. 2. The agent preserves the attacker-controlled text while generating the requested diagram code. 3. Following `SKILL.md`, the agent places the generated code inside the double-quoted `--code` argument. 4. The agent executes the resulting command through a shell. 5. The shell evaluates the injected command substitution before starting Python. 6. The attacke ...[truncated 1072 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not interpolate diagram content into a shell command, even when surrounding it with quotes. 2. Invoke the Python script with an argument-array API that does not use a shell. For example, use Python's `subprocess.run()` with `shell=False` and separate arguments: ```python subprocess.run( [ "python", "scripts/generate_drawio_url.py", "--type", diagram_type, "--code", diagram_code, ], check=True, shell=False, ) ``` 3. Prefer standard input for arbitrary multiline diagram content. Add an option such as `--code-stdin` and read the data with `sys.stdin.read()`. Pass the content using the execution API's standard-input facility rather than a shell pipeline or here-document assembled from user input. 4. Alternatively, write the diagram to a securely created temporary file and pass only its path. Use restrictive permissions, unpredictable filenames, and guaranteed cleanup. 5. Update `SKILL.md` to explicitly prohibit constructing a command string or enabling `shell=True`. 6. Replace the current examples with examples using a shell-free execution interface. If command-line examples must remain, clearly state that they are suitable only for fixed trusted literals and not for generated or user-controlled content. 7. Add tests containing double quotes, backticks, `$()`, semicolons, newlines, and XML/CSV quoting characters to verify that diagram input is treated strictly as data. ]]>
