T09 · Insecure Skill Coding Practices
- Location
scripts/read_weixin_article.py:29- Finding
Arbitrary Command Execution Through Shell Command Injection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/read_weixin_article.py, lines 29-35
Vulnerability Type: OS command injection caused by unsafe shell command construction
Risk Level: CriticalVulnerable Code
python # Use curl to fetch the page cmd = f'curl -s -L --max-time 20' for key, value in headers.items(): cmd += f' -H "{key}: {value}"' cmd += f' "{url}"' import subprocess result = subprocess.run(cmd, shell=True, capture_output=True, text=True)Technical Analysis
The user-controlled
urlargument is interpolated directly into a command string and then passed tosubprocess.runwithshell=True. Quoting the URL with double quotation marks does not make it safe because an attacker can include another double quote followed by shell metacharacters.The shell parses the resulting string rather than passing the URL directly to
curl. Consequently, crafted input can terminate the intended URL argument and introduce arbitrary commands. No escaping, allowlist validation, or shell-safe argument construction is performed.Attack Path
- An attacker supplies a crafted value as the article URL.
- The value contains a closing double quote, shell command separators, and an injected command.
- The script appends the value directly to
cmd. subprocess.run(..., shell=True)asks the system shell to parse the complete command.- The shell executes both the intended
curlinvocation and the attacker-supplied command.
A conceptual malicious argument is:
text "; attacker-controlled-command; #The exact command can be adapted to the operating system and the permissions of the process.
Impact Assessment
Successful exploitation provides arbitrary command execution with the same operating-system identity and privileges as the Agent or user running the Skill. Depending on those privileges, an attacker could:
- Read local files, environment variables, to ...[truncated 421 chars]
- Remediation
View remediation
Remediation Suggestions
Eliminate shell interpretation entirely. Pass each argument as a separate list element and keep
shell=False:python command = ["curl", "-s", "-L", "--max-time", "20"] for key, value in headers.items(): command.extend(["-H", f"{key}: {value}"]) command.append(url) result = subprocess.run( command, shell=False, capture_output=True, text=True, timeout=25, check=False, )Prefer a maintained Python HTTP client so no external command is required. In addition:
- Apply strict URL validation independently of command construction.
- Permit only the expected HTTPS origin and paths.
- Do not attempt to secure this code solely through manual shell escaping.
- Run the Skill under a minimally privileged account with restricted filesystem and network access.
- Add regression tests containing quotes, command separators, substitutions, newlines, and other shell metacharacters.
