T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/memory_health.sh:93
- Finding
- Python Code Injection Through Crafted Session Cache Filenames<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory_health.sh`, lines 93–96 **Vulnerability Type**: OS filename injection into dynamically constructed Python source **Risk Level**: High ### Vulnerable Code ```bash for cache in /tmp/openclaw-session-cache-*.json; do KEYS=$(python3 -c "import json; print(len(json.load(open('$cache'))))" 2>/dev/null || echo 0) echo " $(basename "$cache"): $KEYS entries" done ``` ### Technical Analysis The cache filename comes from a glob over a shared, attacker-writable `/tmp` directory. It is interpolated directly into a Python program passed through `python3 -c`. Although the shell variable is surrounded by shell double quotes, its contents become part of a single-quoted Python string. Unix filenames may contain single quotes, semicolons, parentheses, and hash characters. A crafted filename can therefore terminate the Python string, close the surrounding function calls, insert additional Python statements, and comment out the remaining source. This is code injection rather than ordinary shell injection: the shell safely expands the variable, but the resulting value is interpreted as Python source. ### Attack Path 1. A local attacker creates a valid JSON file that will satisfy the initial `open()` operation: ```bash printf '{}' > /tmp/openclaw-session-cache-x ``` 2. The attacker creates a matching filename whose basename contains Python syntax, conceptually: ```text /tmp/openclaw-session-cache-x'))));__import__('os').system('id');#.json ``` 3. The agent or user runs: ```bash bash scripts/memory_health.sh ``` 4. The glob includes the crafted filename. 5. The filename is inserted into the `python3 -c` program. 6. The injected Python expression invokes `os.system()` with the privileges of the process running the health script. The payload can be changed from `id` to commands that read, modify, or delete files accessible to the agent account. ### Impact Assessment ...[truncated 503 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Never interpolate filenames into executable Python source. Pass the path as a positional argument: ```bash for cache in /tmp/openclaw-session-cache-*.json; do KEYS=$( python3 -c \ 'import json, sys; print(len(json.load(open(sys.argv[1], encoding="utf-8"))))' \ "$cache" 2>/dev/null || echo 0 ) printf ' %s: %s entries\n' "$(basename -- "$cache")" "$KEYS" done ``` Additional hardening should include: 1. Store caches in a private, user-owned directory with mode `0700` rather than shared `/tmp`. 2. Reject symbolic links and non-regular files before reading. 3. Avoid enumerating cache files belonging to other sessions or users. 4. Use a Python health-check implementation so paths are passed as data throughout. 5. Add regression tests using filenames containing quotes, semicolons, newlines, and parentheses. ]]>
