T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/run-upgrade-delegation.sh:217
- Finding
- Arbitrary Python Code Execution Through an Unsafely Embedded Result Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run-upgrade-delegation.sh`, lines 217–218 **Vulnerability Type**: Python source injection caused by unsafe string interpolation **Risk Level**: High ### Vulnerable Code ```bash if [[ -f "$RESULT_JSON" ]]; then FINAL_STATUS="$(python3 -c "import json; print(json.load(open('$RESULT_JSON')).get('status','unknown'))")" ``` ### Technical Analysis `RESULT_JSON` is initialized from the script's second positional argument: ```bash RESULT_JSON="${2:-$HOME/.openclaw/.upgrade-result.json}" ``` Although the shell expands `"$RESULT_JSON"` within a double-quoted argument, the expanded value is inserted directly into the Python program passed to `python3 -c`. The single quotes around `$RESULT_JSON` are Python syntax, not a security boundary enforced by the shell. A result path containing an apostrophe and additional Python expressions can terminate the intended Python string and inject arbitrary Python code. The vulnerable command is reached when: 1. `OPENCLAW_UPGRADER_DELEGATE_CMD` is configured. 2. The delegation command returns a nonzero status. 3. A file exists at the attacker-selected `RESULT_JSON` path. No evaluation of the path as source code is necessary. It should instead be passed to Python as a separate command-line argument. ### Attack Path 1. An attacker who can invoke the runner or influence its arguments supplies a crafted second positional argument containing Python syntax. 2. The attacker ensures that a file exists under the resulting crafted pathname. 3. The configured delegation command returns a nonzero exit code, causing execution to enter the error-handling branch. 4. Line 218 interpolates the malicious pathname into the Python source supplied through `python3 -c`. 5. Python evaluates the injected expression or statements with the operating-system privileges of the upgrader process. A conceptual malicious path could close the `open('...')` string and append an expression invoki ...[truncated 891 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Pass the result path as data through `sys.argv` rather than embedding it into Python source: ```bash FINAL_STATUS="$( python3 -c \ 'import json, sys; print(json.load(open(sys.argv[1])).get("status", "unknown"))' \ "$RESULT_JSON" )" ``` Additional hardening should include: 1. Parse the result file in a dedicated quoted heredoc or standalone helper where all dynamic values are supplied as arguments. 2. Validate that the result file is a regular file and, where appropriate, is owned by the expected user. 3. Restrict result files to an expected directory after canonicalizing the path. 4. Avoid dynamically constructing source code from shell variables anywhere in the scripts. 5. Add regression tests using paths containing apostrophes, spaces, newlines, shell metacharacters, and Python syntax. 6. Treat malformed or untrusted result JSON as a controlled delegation failure rather than allowing an unhandled parser error. ]]>
