T09 · Insecure Skill Coding Practices
- Location
scripts/gemini_prompt.sh:7- Finding
Arbitrary Command Execution Through Shell Command Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/gemini_prompt.sh, lines 7–17
Vulnerability Type: Shell command injection through untrusted prompt and executable-path interpolation
Risk Level: HighVulnerable Code
bash PROMPT=${1:-} if [[ -z "${PROMPT}" ]]; then echo "Usage: $0 \"<prompt>\"" >&2 exit 2 fi GEMINI_BIN="${GEMINI_BIN:-$HOME/.npm-global/bin/gemini}" # 'script' allocates a pseudo-terminal; /dev/null avoids creating a typescript file. script -q -c "${GEMINI_BIN} -p \"${PROMPT//\"/\\\"}\"" /dev/nullTechnical Analysis
The script constructs a single command string from
GEMINI_BINandPROMPT, then passes it toscript -c. Thescriptutility invokes a shell to interpret that string. Consequently, prompt content is parsed as shell syntax rather than being passed directly to Gemini as an opaque argument.The attempted sanitization only escapes double-quote characters. It does not neutralize command substitutions such as
$()or backticks, nor other shell metacharacters and expansions. Although variable contents are not recursively evaluated during the first shell's parameter expansion, the resulting string is parsed again by the shell launched throughscript -c, at which point injected shell constructs are executed.GEMINI_BINis also taken from the caller-controlled environment and inserted into the same command string without validation or shell-safe quoting. An attacker able to influence this variable can inject commands independently of the prompt.Attack Path
- The victim or an Agent invokes
gemini_prompt.shwith attacker-controlled text, such as content copied from an untrusted request. - The text contains shell command substitution, for example a prompt containing
$(malicious-command). - The script escapes only embedded double quotes and concatenates the prompt into the argument supplied to
script -c. scriptlaunches a she ...[truncated 1342 chars]
- The victim or an Agent invokes
- Remediation
View remediation
Remediation Suggestions
- Do not interpolate prompts or executable paths into a command string interpreted by a shell. Pass the Gemini executable and prompt as distinct arguments through an interface that does not perform shell parsing.
- If pseudo-terminal allocation is mandatory, use a PTY mechanism that accepts an argument array rather than a single
-ccommand string. A small Python wrapper using the standardptyandos.execvoros.execveAPIs is one suitable approach. - Pin
GEMINI_BINto a trusted, absolute executable path. If configurability is required, validate the configured value as a single existing executable file and never interpret it as shell syntax. - If retaining
script -cis unavoidable, generate a command from individually shell-quoted arguments using a robust mechanism such as Bashprintf '%q'. Apply quoting separately to both the executable path and prompt. This is less preferable than eliminating the second shell entirely. - Add regression tests using prompts containing
$(), backticks, semicolons, quotes, newlines, redirections, and pipe characters. Verify that each value reaches Gemini literally and causes no local side effects. - Update the command templates in
SKILL.mdso users are not encouraged to place untrusted prompt text directly into shell-interpreted command strings.
