T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/tenk.sh:136
- Finding
- Python Code Injection Through the Skill Query<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tenk.sh`, lines 136–155 **Vulnerability Type**: Python source-code injection **Risk Level**: High ### Vulnerable Code ```bash skill_id=$(echo "$skills_resp" | python3 -c " import json, sys q = '$skill_query'.lower() skills = json.load(sys.stdin).get('data', []) match = next((s for s in skills if q in s['name'].lower()), None) if match: print(match['id']) " 2>/dev/null) skill_name=$(echo "$skills_resp" | python3 -c " import json, sys q = '$skill_query'.lower() skills = json.load(sys.stdin).get('data', []) match = next((s for s in skills if q in s['name'].lower()), None) if match: print(match['name']) " 2>/dev/null) ``` ### Technical Analysis The caller-controlled `skill_query` value is interpolated directly into two programs passed to `python3 -c`. Shell quoting protects how the shell passes the overall program argument, but it does not make the interpolated content safe Python syntax. A skill query containing a single quote and additional Python statements can terminate the intended string literal and alter the program executed by Python. Because Python exposes operating-system functionality through modules such as `os` and `subprocess`, successful injection can become arbitrary local command execution. The same unsafe construction appears twice: once while resolving the skill identifier and again while resolving the skill name. ### Attack Path 1. An attacker influences the skill name supplied to the `log` command, potentially through a chat request processed by the Agent. 2. The Agent invokes `tenk.sh log` with the crafted value as `skill_query`. 3. Bash substitutes that value into the source string passed to `python3 -c`. 4. The crafted value closes the intended Python string and introduces attacker-selected Python statements. 5. Python executes those statements with the privileges and environment of the user running the Agent. ### Impact Assessment Successful exploitation provide ...[truncated 457 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Never insert command-line input into dynamically generated Python source. Keep the Python program constant and pass the query as a positional argument: ```bash skill_id=$(printf '%s' "$skills_resp" | python3 -c ' import json import sys query = sys.argv[1].lower() skills = json.load(sys.stdin).get("data", []) match = next( (skill for skill in skills if query in skill.get("name", "").lower()), None, ) if match: print(match["id"]) ' "$skill_query") ``` Resolve both the identifier and name in one fixed Python invocation where practical. In addition: - Treat command-line arguments and chat-derived values as untrusted. - Use `sys.argv` or environment variables only as data channels. - Do not use `eval`, generated source, or source-string interpolation. - Add regression tests using values containing quotes, semicolons, newlines, backslashes, and Python syntax. ]]>
