T09 · Insecure Skill Coding Practices
- Location
scripts/batch-setup.sh:38- Finding
Arbitrary Python Code Execution Through Manifest Path Injection
- Content
View full analysis
/dev/null; then echo "❌ Invalid JSON in manifest file" exit 1 fi ``` The same unsafe interpolation pattern appears again during agent registration: ```bash python3 -c " import json, subprocess, os state_dir = os.environ.get('OPENCLAW_STATE_DIR', os.path.expanduser('~/.openclaw')) with open('$MANIFEST') as f: agents = json.load(f) ``` ### Technical Analysis The user-supplied manifest path is interpolated directly into Python source code inside a single-quoted Python string. Shell quoting does not make this safe because the expanded filename becomes part of the source passed to `python3 -c`. A filename containing a single quote, closing parentheses, semicolons, and Python statements can terminate the intended string and append arbitrary Python code. This is source-code injection rather than ordinary argument injection. For example, a crafted filename shaped like the following can close the `open()` and `json.load()` calls before appending a command: ```text x'));__import__("os").system("id");# ``` The initial validation command is already vulnerable, so exploitation occurs before the script creates workspaces or validates the manifest's intended schema. ### Attack Path 1. An attacker creates a valid JSON manifest whose filename contains Python syntax. 2. The attacker or a victim invokes: ```bash ./scripts/batch-setup.sh '' ``` 3. The shell expands `$MANIFEST` inside the string passed to `python3 -c`. 4. The filename terminates the Python string and injects additional statements. 5. Python executes the injected statements with the privileges of the user running the setup script. 6. The p ...[truncated 857 chars]- Remediation
View remediation
/dev/null; then echo "Invalid JSON in manifest file" exit 1 fi ``` Apply the same correction to the registration block: ```bash python3 - "$MANIFEST" <<'PYEOF' import json import os import subprocess import sys manifest_path = sys.argv[1] state_dir = os.environ.get( "OPENCLAW_STATE_DIR", os.path.expanduser("~/.openclaw"), ) with open(manifest_path, encoding="utf-8") as f: agents = json.load(f) # Continue registration using the parsed data. PYEOF ``` Alternatively, consistently use the existing `MANIFEST_PATH` environment variable inside quoted heredocs. Do not construct executable Python, shell, or JSON expressions through string interpolation. Add regression tests using filenames containing quotes, semicolons, spaces, newlines, parentheses, and shell metacharacters. ]]>
