T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/analyze.py:34
- Finding
- OS Command Injection Through Stock Search Input## Vulnerability Details **File Location**: `scripts/analyze.py`, lines 34–35 **Vulnerability Type**: OS command injection through shell command construction **Risk Level**: High ### Vulnerable Code ```python cmd = f"node ~/.workbuddy/skills/westock-data/scripts/index.js search '{self.stock_input}'" result = subprocess.run(cmd, shell=True, capture_output=True, text=True) ``` The value used here originates from a command-line argument: ```python stock_input = sys.argv[1] analyzer = StockDecisionAnalyzer(stock_input) ``` ### Technical Analysis `self.stock_input` is derived directly from `sys.argv[1]` and interpolated into a command string executed with `shell=True`. Although the value is enclosed in single quotes, this is not safe shell escaping. An attacker can include a single quote to terminate the quoted argument and then append shell operators and commands. The shell interprets the resulting string rather than passing the stock input as an opaque argument to Node.js. No stock-name validation or robust shell escaping prevents this behavior. ### Attack Path 1. An attacker supplies a malicious stock-name argument to `analyze.py`. 2. The argument is stored in `self.stock_input`. 3. `search_stock()` inserts it into the shell command without safe argument separation. 4. A quote in the input terminates the intended shell argument. 5. Shell metacharacters append an attacker-selected command. 6. `subprocess.run(..., shell=True)` executes that command with the privileges of the Python process. For example, an argument structurally resembling the following can escape the quoted value: ```text ' ; ATTACKER_COMMAND ; # ``` ### Impact Assessment Successful exploitation permits arbitrary command execution under the account running the skill. The attacker could read or modify files accessible to that account, invoke local tools, alter skill data, access environment-provided secrets, or execute additional programs. The flaw does not independently elevate privil ...[truncated 151 chars]
- Remediation
- ## Remediation Suggestions Do not invoke a shell. Resolve the script path in Python and pass each argument separately: ```python from pathlib import Path import subprocess script_path = Path( "~/.workbuddy/skills/westock-data/scripts/index.js" ).expanduser() result = subprocess.run( ["node", str(script_path), "search", self.stock_input], shell=False, capture_output=True, text=True, timeout=30, check=False, ) ``` Additionally: 1. Validate the input against documented stock-name and stock-code constraints. 2. Apply a reasonable maximum input length. 3. Reject control characters and unexpected line breaks. 4. Add tests containing quotes, semicolons, command substitutions, pipes, and newlines. 5. Run the skill with minimum filesystem and environment access so that any future command-execution flaw has reduced impact.
