T09 · Insecure Skill Coding Practices
- Location
SKILL.md:67- Finding
Shell Command Injection Through Custom Language Persistence
- Content
View full analysis
" > ~/.lista/language.txt ``` The `` placeholder may contain a user-provided custom language name. The Skill does not require validation, shell-safe encoding, or use of a non-shell filesystem interface before substituting this value into the command. ### Technical Analysis The command places attacker-controlled content inside a double-quoted shell argument. Double quotes do not suppress shell command substitution. Consequently, input containing constructs such as `$(...)` may be evaluated by the shell rather than written exclusively as literal data. Custom language names are intentionally unrestricted by the Skill. Unlike the predefined values `en`, `zh-CN`, and `zh-TW`, no allowlist or character validation is specified for an “Other” language. This creates a direct data-to-command boundary violation. The vulnerability depends on the Agent following the documented command by textual placeholder substitution. An input equivalent to: ```text $(id > /tmp/lista-language-injection) ``` could produce an effective command resembling: ```bash mkdir -p ~/.lista && echo "$(id > /tmp/lista-language-injection)" > ~/.lista/language.txt ``` The shell would execute the command substitution before invoking `echo`. ### Attack Path 1. The Skill asks the user to choose an output language. 2. The attacker selects “Other” and supplies a crafted custom language name containing shell syntax. 3. The Agent substitutes the value directly for `` in the documented shell command. 4. The shell evaluates command substitutions or other successfully injected syntax. 5. The injected command executes with the same operating-system privileges as the Agent process. 6. The legitimate language file write may still complete ...[truncated 889 chars]- Remediation
View remediation
"$HOME/.lista/language.txt"' sh "" ``` 7. Prefer an implementation equivalent to the following non-shell logic: ```javascript await fs.promises.mkdir(path.join(os.homedir(), '.lista'), { recursive: true }); await fs.promises.writeFile( path.join(os.homedir(), '.lista', 'language.txt'), validatedChoice + '\n', { encoding: 'utf8', mode: 0o600 } ); ``` 8. Add tests confirming that values containing `$()`, backticks, quotes, semicolons, newlines, and redirection operators are rejected or stored literally without execution. ]]>
