T09 · Insecure Skill Coding Practices
- Location
- SKILL.md:89
- Finding
- Shell Command Injection Through Generated Content<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:89-102` and `SKILL.md:119-128` **Vulnerability Type**: Shell command injection through unsafe interpolation **Risk Level**: High ### Vulnerable Code ```bash # Save prompts cat > {SKILL_DIR}/output/$(date +%Y-%m-%d)/prompts.json << 'EOF' <video_prompts array> EOF # Run the full pipeline python3 {SKILL_DIR}/scripts/video_pipeline.py create \ --prompts {SKILL_DIR}/output/$(date +%Y-%m-%d)/prompts.json \ --output {SKILL_DIR}/output/$(date +%Y-%m-%d) \ --text "<overlay_text separated by |>" \ --bgm-dir {SKILL_DIR}/bgm \ --mood <bgm_mood> ``` ```bash python3 {SKILL_DIR}/scripts/xhs_publish.py video \ --title "<xhs_title>" \ --content "<xhs_content>" \ --video "{SKILL_DIR}/output/$(date +%Y-%m-%d)/final.mp4" \ --tags "<comma-separated tags>" ``` ### Technical Analysis The Skill instructs the agent to substitute generated prompts, overlay text, titles, post content, tags, and mood values directly into shell command text. These values can be influenced by persona files, prompt templates, user input, or model-generated output. Double quotes do not prevent shell evaluation of command substitutions such as `$(command)` or backticks. Embedded quotation marks can also terminate an argument and introduce shell operators. In addition, a prompt containing a line equal to `EOF` can terminate the heredoc early, allowing subsequent lines to be interpreted as shell commands. The affected values are not passed through a structured process API, and the instructions do not require shell-safe quoting or input validation. ### Attack Path 1. An attacker introduces crafted content through a user-supplied topic, modified persona, prompt template, or other input used to generate the post. 2. The generated field contains shell syntax, such as a quote followed by a command separator, a command substitution, or a standalone `EOF` line. 3. The agent substitutes that field into one of the documented shell ...[truncated 776 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not construct shell commands by interpolating generated content. 2. Write `prompts.json` and `metadata.json` with a JSON library rather than a shell heredoc. 3. Invoke Python scripts through a process API using an argument array and with shell evaluation disabled, for example: ```python subprocess.run( [ "python3", pipeline_path, "create", "--prompts", prompts_path, "--output", output_dir, "--text", overlay_text, "--bgm-dir", bgm_dir, "--mood", mood, ], shell=False, check=True, ) ``` 4. Apply an allowlist to `bgm_mood` and validate title, tag, path, and overlay-text lengths and character sets. 5. Pass long-form post content through a temporary file or standard input instead of embedding it in a command. 6. If shell execution is unavoidable, use a platform-appropriate quoting library and reject newlines, heredoc terminators, command substitutions, and shell metacharacters. Structured process invocation remains the preferred control. ]]>
