T09 · Insecure Skill Coding Practices
- Location
scripts/validate.sh:34- Finding
Arbitrary Python Code Execution Through Crafted Profile Filenames
- Content
View full analysis
/dev/null; then ``` ```bash ISSUES=$(python3 -c " import json, sys with open('$f') as fh: d = json.load(fh) ``` ```bash sname=$(python3 -c "import json; print(json.load(open('$f')).get('systemName',''))" 2>/dev/null || echo "") ``` ### Technical Analysis The script interpolates the profile pathname stored in `$f` directly into Python source passed to `python3 -c`. Shell quoting does not make the resulting value safe as a Python string literal. A profile filename containing a single quote and valid Python syntax can terminate the `open('...')` expression and inject additional Python statements. The injected code is then executed by `python3` with the privileges of the user running the validation script. The vulnerability occurs in three separate Python invocations. The first invocation is sufficient to reach code execution before the profile's JSON contents are trusted or validated. ### Attack Path 1. An attacker obtains the ability to add or rename a `.json` file under the configured `docs/agent-profiles` directory. 2. The attacker gives the file a crafted name containing Python syntax designed to escape the single-quoted pathname literal. 3. A user, automation process, or Agent runs `bash scripts/validate.sh`. 4. The shell expands `$f` into the `python3 -c` source code. 5. Python parses and executes the attacker-supplied syntax. 6. The payload runs with the invoking user's permissions. ### Impact Assessment Successful exploitation provides arbitrary local code execution under the account that invokes `validate.sh`. The attacker could read or modify files accessible to that account, alter project content, steal locally available credentials, or execute additional operating-system commands. ...[truncated 242 chars]- Remediation
View remediation
/dev/null; then ``` For the larger validation block, pass the path after the Python program: ```bash ISSUES=$(python3 - "$f" <<'PYEOF' import json import os import sys path = sys.argv[1] with open(path) as fh: d = json.load(fh) expected_name = os.path.splitext(os.path.basename(path))[0] # Continue validation here. PYEOF ) ``` Apply the same pattern to the uniqueness lookup: ```bash sname=$(python3 -c \ 'import json, sys; print(json.load(open(sys.argv[1])).get("systemName", ""))' \ "$f" 2>/dev/null || echo "") ``` Use a single-quoted heredoc delimiter where possible so the shell cannot expand data inside Python source. Add regression tests using filenames containing quotes, spaces, command-substitution characters, newlines, and semicolons. ]]>
