T09 · Insecure Skill Coding Practices
- Location
market_watcher.py:133- Finding
Arbitrary Python Code Execution Through Alert Message Interpolation
- Content
View full analysis
bool: """Push an alert to Feishu through the message tool.""" try: from message_tool import message # Dynamic import to avoid circular dependencies import subprocess result = subprocess.run( ['python3', '-c', f'from tools import message; message(action="send", channel="feishu", target="user:ou_fd61d5ebc9af22913aa4c21c8e3cac14", message="{alert_msg}")'], capture_output=True, text=True, timeout=15, cwd='/workspace' ) return result.returncode == 0 except Exception: return False ``` ### Technical Analysis The function embeds `alert_msg` directly into Python source code and executes the resulting source using `python3 -c`. Although `subprocess.run` is invoked without `shell=True`, this does not prevent code injection because the Python interpreter itself processes the attacker-controlled string as executable source. An alert containing quotes, line breaks, backslashes, or Python syntax can terminate the intended string literal and append arbitrary statements. A representative payload shape is: ```python '"); __import__("os").system("ATTACKER_COMMAND"); #' ``` Once interpolated, the child interpreter executes the injected statement with the same operating-system identity, environment, filesystem access, and network permissions as the watcher process. ### Attack Path 1. An attacker gains control over, or influences, a value passed to `push_to_feishu(alert_msg)`. 2. The attacker supplies text that closes the `message` argument string and injects additional Python statements. 3. The function inserts that text into the source supplied to `python3 -c`. 4. The newly launched Pyth ...[truncated 1055 chars]- Remediation
View remediation
bool: try: from tools import message message( action="send", channel="feishu", target=target, message=alert_msg, ) return True except Exception: return False ``` If a separate process is operationally required: 1. Create a fixed child script containing no dynamically generated source. 2. Pass message content through standard input or a JSON data file. 3. Parse the input strictly as data in the child process. 4. Never interpolate data into `-c`, `eval`, `exec`, shell commands, or source templates. 5. Run the child with minimum filesystem and network privileges. 6. Add tests containing quotes, backslashes, newlines, semicolons, and code-like payloads to verify that all content remains inert data. ]]>
