T09 · Insecure Skill Coding Practices
- Location
SKILL.md:17- Finding
Shell Command Injection Through Direct Prompt Interpolation
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:17-17,SKILL.md:46-57
Vulnerability Type: Shell command injection through unsafe command construction
Risk Level: HighVulnerable Code
markdown - **Use the user's complete original input**: Pass the user's complete original request directly as the main body of the `-p` prompt.bash node scripts/generate_image.js -p "{prompt}" -f "{filename}" [-a {ratio}] [-r {res}] node scripts/generate_image.js -p "{edit_instruction}" -i "{input_path}" -f "{output_filename}" [-r {res}] python scripts/generate_image.py -p "{prompt}" -f "{filename}" [-a {ratio}] [-r {res}] python scripts/generate_image.py -p "{edit_instruction}" -i "{input_path}" -f "{output_filename}" [-r {res}]Technical Analysis
The Skill directs the Agent to preserve the user's raw input and interpolate it into a textual shell command enclosed in double quotes. Double quotes do not neutralize every shell metacharacter. If the Agent executes the generated command through a shell, a malicious prompt containing a closing quote, command substitution, or another shell expression can alter the command's syntax.
The underlying Python and Node.js programs parse arguments without invoking a shell and are not independently vulnerable when launched through a safe argument-array API. The vulnerability arises from the Skill-level execution instructions, which encourage construction of a command string from untrusted input without specifying shell-free invocation or robust argument escaping.
Attack Path
- An attacker submits an image-generation prompt containing shell syntax.
- Following
SKILL.md:17, the Agent preserves the attacker's complete input. - The Agent substitutes that input into one of the command templates at
SKILL.md:46-57. - If the resulting string is passed to a shell, the shell interprets the injected syntax rather than treating the entire prompt as one litera ...[truncated 750 chars]
- Remediation
View remediation
Remediation Suggestions
-
Do not construct a shell command by interpolating the prompt, filename, or input path into a string.
-
Invoke the program through a shell-free argument-array interface, such as Node.js
spawnorexecFilewithshell: false, or Pythonsubprocess.run([...], shell=False). -
Update
SKILL.mdto explicitly prohibitshell=True,exec,system, and equivalent shell-string execution. -
Pass each value as a distinct argument, for example:
javascript spawn('node', [ 'scripts/generate_image.js', '--prompt', prompt, '--filename', filename ], { shell: false }); -
Validate filenames, ratios, resolutions, and input paths independently. Validation must be supplemental; it must not replace shell-free invocation.
-
Add regression tests using prompts containing quotes, semicolons, newlines, dollar signs, backticks, and command-substitution syntax to confirm that they remain literal prompt data.
-
