T09 · Insecure Skill Coding Practices
- Location
SKILL.md:55- Finding
Shell Command Injection Through Unsafely Interpolated User Input
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:55,SKILL.md:93, andSKILL.md:165
Vulnerability Type: Shell command injection
Risk Level: HighVulnerable Code
bash python {baseDir}/scripts/parser.py "<用户输入>"bash python {baseDir}/scripts/bookkeeper.py add '<json>'bash python {baseDir}/scripts/bookkeeper.py search "<关键词>"Technical Analysis
The skill instructs the agent to interpolate user-controlled bookkeeping text, search keywords, and generated JSON directly into shell command strings. Shell quoting does not make this construction safe:
- Inside double quotes, command substitutions such as
$(command)and backtick substitutions can still be evaluated by the shell. - A single quote embedded in generated JSON can terminate the single-quoted argument used by the
addcommand, allowing additional shell syntax to be introduced. - Generated JSON may contain attacker-controlled fields such as the raw input or note, so treating generated JSON as trusted does not eliminate the injection risk.
Exploitation depends on these documented commands being executed through a shell. The referenced scripts are absent from the audited package, so their own argument handling could not be reviewed; however, shell expansion occurs before Python receives the arguments.
Attack Path
- An attacker supplies bookkeeping text or a search keyword containing shell syntax, such as a command substitution.
- The agent inserts that value into one of the command templates in
SKILL.md. - The command is passed to a shell for execution.
- The shell evaluates the injected substitution or syntax before launching the intended Python program.
- The attacker's command executes with the operating-system permissions of the agent or skill runtime.
For the
addoperation, an attacker can instead place a single quote and shell metacharacters in a note or raw-input fie ...[truncated 915 chars]- Inside double quotes, command substitutions such as
- Remediation
View remediation
Remediation Suggestions
- Do not build shell command strings from user-controlled values. Invoke Python using an argument-array API with shell processing disabled, for example the equivalent of
subprocess.run(["python", script_path, user_input], shell=False, check=True). - Pass structured bookkeeping records to the program through standard input or a securely created JSON file rather than embedding serialized JSON in shell source.
- If a shell is unavoidable, apply platform-appropriate escaping to every dynamic argument. Escaping should be treated as a fallback rather than the primary control.
- Validate record fields against strict schemas, including amount type and range, date format, transaction type, identifier format, maximum text length, and allowed control characters.
- Require deletion identifiers and year/month parameters to be parsed as bounded integers before invocation.
- Add the missing scripts to the package and perform a separate audit of their SQL construction, HTML output encoding, file permissions, path handling, and error handling.
- Add automated tests containing single quotes, double quotes, backticks, command substitutions, semicolons, newlines, and shell redirection characters to verify that all values reach Python only as literal data.
- Do not build shell command strings from user-controlled values. Invoke Python using an argument-array API with shell processing disabled, for example the equivalent of
