T09 · Insecure Skill Coding Practices
Error
- Location
- dream-tools.sh:454
- Finding
- Arbitrary Python Code Execution Through Unvalidated Timestamp State<![CDATA[ ## Vulnerability Details **File Location**: `dream-tools.sh`, lines 454-463 **Vulnerability Type**: Python source injection through unsafe string interpolation **Risk Level**: High ### Vulnerable Code ```bash local last_review="Never" local hours_since="-" if [[ -f "$last_review_file" ]]; then last_review=$(cat "$last_review_file") # Calculate hours since last distillation if command -v python3 &>/dev/null; then hours_since=$(python3 -c " from datetime import datetime last = datetime.strptime('$last_review', '%Y-%m-%d %H:%M') diff = datetime.now() - last print(int(diff.total_seconds() / 3600)) " 2>/dev/null || echo "-") fi fi ``` ### Technical Analysis The contents of `meta/last-review.txt` are read into `last_review` and interpolated directly into source code passed to `python3 -c`. Shell quoting does not make this safe because the value is inserted inside a Python string literal. A malicious timestamp containing a single quote followed by valid Python statements can terminate the intended string and inject arbitrary Python code. For example, a crafted value can import `os` and invoke system commands before commenting out the remainder of the generated line. The script neither validates the timestamp format before interpolation nor passes the value through a non-code channel such as a command-line argument or environment variable. The exception fallback does not prevent exploitation because injected statements execute before a later parsing error is handled by the shell. ### Attack Path 1. An attacker, another local process, or an agent operation modifies: `DREAM_VAULT_PATH/meta/last-review.txt`. 2. The attacker supplies content designed to terminate the Python string and insert Python statements. 3. The user or agent invokes: ```bash dream-tools.sh --status ``` 4. `cmd_status` places the malicious file content directly into the program passed to `python3 -c`. 5. Python executes the injected statements with ...[truncated 541 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Never interpolate file content into executable Python source. Pass the timestamp as a positional argument: ```bash if [[ "$last_review" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}\ [0-9]{2}:[0-9]{2}$ ]]; then hours_since=$(python3 - "$last_review" <<'PY' from datetime import datetime import sys last = datetime.strptime(sys.argv[1], "%Y-%m-%d %H:%M") diff = datetime.now() - last print(int(diff.total_seconds() / 3600)) PY ) || hours_since="-" else hours_since="-" fi ``` Additional hardening should include: - Require the timestamp to match the exact expected syntax before parsing. - Reject multiline input and unexpected file sizes. - Ensure the state file and its parent directory are writable only by the OpenClaw account. - Avoid constructing source code dynamically from any persisted state. - Add regression tests using quotes, newlines, semicolons, Python expressions, and malformed timestamps. ]]>
