T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/grow.sh:261
- Finding
- Arbitrary Python Code Execution Through Shell-to-Python Source Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/grow.sh`, lines 261-286 **Vulnerability Type**: Python source injection leading to arbitrary command execution **Risk Level**: High ### Vulnerable Code ```bash # Add record python3 -c " import json with open('$DATA_FILE') as f: data = json.load(f) record = { 'id': '$record_id', 'date': '$date_short', 'timestamp': '$now', 'description': '$description', 'domain': '$domain', 'xp': $xp, 'type': '$type' } data['records'].append(record) data['totalXp'] = $new_xp data['chromeLevel'] = $new_level data['profile']['title'] = '$(get_title "$new_level")' if '$domain' not in data['domains']: data['domains']['$domain'] = {'xp': 0, 'level': 1} data['domains']['$domain']['xp'] = $new_domain_xp data['domains']['$domain']['level'] = $domain_level with open('$DATA_FILE', 'w') as f: json.dump(data, f, indent=2, ensure_ascii=False) " 2>/dev/null ``` The same unsafe construction pattern also occurs in other Python invocations, including configurable file paths and command options at `scripts/grow.sh:60-88`, `scripts/grow.sh:492-503`, `scripts/grow.sh:581-632`, `scripts/grow.sh:833-846`, `scripts/grow.sh:938-989`, and `scripts/grow.sh:1050-1067`. ### Technical Analysis The script creates Python source code inside a double-quoted shell string and directly inserts values such as `description`, `domain`, `type`, `xp`, and `DATA_FILE`. These values are treated as Python syntax rather than serialized data. For example, a description containing a single quote can terminate the Python string assigned to `description`. Additional Python statements can then be inserted into the generated program. Python provides direct access to operating-system functionality through modules such as `os` and `subprocess`, so successful source injection results in arbitrary command execution. Suppressing standard error with `2>/dev/null` does not prevent exploitation. It only hides syntax errors an ...[truncated 1873 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never construct Python source code by interpolating shell variables. 2. Pass values as command-line arguments or environment variables and retrieve them through `sys.argv` or `os.environ`. 3. Prefer a separate Python script over large `python3 -c` strings. 4. Serialize records with `json.dump` or `json.dumps`; do not manually quote input. 5. Validate `xp`, `days`, chart ranges, and log limits as bounded integers before use. 6. Validate months and dates against strict formats such as `^[0-9]{4}-[0-9]{2}$` and `^[0-9]{4}-[0-9]{2}-[0-9]{2}$`. 7. Restrict domains and event types to explicit allowlists. 8. Pass `DATA_FILE` as an argument and open the supplied path as data rather than embedding it in Python source. 9. Stop suppressing all Python errors. Handle failures explicitly and avoid reporting success when a database update failed. 10. Add regression tests containing quotes, backslashes, newlines, Unicode, and Python-like payload text. A safer pattern is: ```bash python3 - "$DATA_FILE" "$record_id" "$date_short" "$now" \ "$description" "$domain" "$xp" "$type" <<'PY' import json import sys data_file, record_id, date_short, now, description, domain, xp, event_type = sys.argv[1:] xp = int(xp) with open(data_file, encoding="utf-8") as handle: data = json.load(handle) record = { "id": record_id, "date": date_short, "timestamp": now, "description": description, "domain": domain, "xp": xp, "type": event_type, } PY ``` ]]>
