T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:87
- Finding
- Shell Command Injection Through Untrusted JSON and Text Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 87-103 and 139-156 **Vulnerability Type**: Shell command injection caused by embedding untrusted data in single-quoted command arguments **Risk Level**: High ### Vulnerable Code ```bash python3 {SKILL_DIR}/scripts/order_helper.py load-default-meal --time-slot <slot> --menu '<data_json>' ``` ```bash python3 {SKILL_DIR}/scripts/order_helper.py calorie-pairing \ --menu '<data_json>' \ --nutrition-text '<raw_text>' \ --time-slot <slot> ``` ```bash python3 {SKILL_DIR}/scripts/order_helper.py format-order-summary \ --items '<cart_items_json>' \ --price '<calculate_price_result_json>' \ --address '<selected_address_json>' ``` ```bash python3 {SKILL_DIR}/scripts/order_helper.py gen-pay-qr --pay-url '<payUrl>' ``` ### Technical Analysis The skill instructs the agent to interpolate MCP responses, menu data, nutrition text, addresses, cart contents, pricing responses, and payment URLs directly into shell commands. Wrapping a value in single quotes does not make interpolation safe if the value itself can contain a single quote. For example, a menu item, address field, nutrition entry, or remote response containing the following value can terminate the quoted argument and append a new shell command: ```text '; id > /tmp/injected # ``` The resulting command would be interpreted approximately as: ```bash python3 order_helper.py ... --menu ''; id > /tmp/injected #' ``` The Python script safely parses its arguments with `argparse`, but this occurs only after the invoking shell has parsed and executed the injected command. Therefore, the JSON parser does not mitigate this issue. The affected values originate from remote MCP responses or user-controlled order and address data. A compromised service response, malicious upstream record, or crafted user field could consequently cross the data-to-command boundary. ### Attack Path 1. An attacker causes an MCP response or user-controlled f ...[truncated 1149 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not construct shell command strings containing MCP or user-controlled data. - Invoke the helper with an argument-array API that does not use a shell, such as Python's `subprocess.run([...], shell=False)`. - Prefer passing structured data over standard input: ```python subprocess.run( ["python3", helper_path, "load-default-meal", "--time-slot", slot, "--menu-file", menu_path], check=True, shell=False, ) ``` - Alternatively, write JSON to a securely created file and pass only its path. - If shell execution is unavoidable, apply platform-appropriate argument escaping to every dynamic value. This is less robust than avoiding the shell. - Validate the schema and maximum size of all MCP responses before processing them. - Avoid including secrets in the environment of processes that handle untrusted data where practical. - Add regression tests using quotes, command substitutions, newlines, and shell metacharacters in every dynamic field. ]]>
