T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:112
- Finding
- Shell Command Injection Through Unquoted Callback Concatenation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:112-138` **Vulnerability Type**: Shell command injection **Risk Level**: High ### Vulnerable Code ```python # 1. Handle callback result = exec(command="python3 ~/.openclaw/workspace/skills/telegram-file-browser/scripts/browser_dispatcher.py handle-callback " + callback_data) response = json.loads(result.stdout) ``` The accompanying callback detection instructions state: ```text - if inbound text matches `^tfb_(root|dir|preview|path|download|back|close)_` - treat it as a telegram-file-browser callback - run `browser_dispatcher.py handle-callback <that_text>` immediately ``` ### Technical Analysis The Skill instructs an agent to concatenate attacker-influenced `callback_data` directly into a command string passed to the `exec` tool. No shell quoting or complete callback validation is applied before constructing the command. The documented detection expression only verifies that inbound text starts with an accepted prefix. It is not anchored at the end and does not prevent shell metacharacters, substitutions, redirections, or additional commands from appearing after the valid-looking prefix. If the OpenClaw `exec` tool evaluates the supplied command through a shell, characters such as command separators or command substitutions in the inbound callback can be interpreted by that shell rather than being passed only as an argument to `browser_dispatcher.py`. The Python implementation itself uses argument arrays when launching its child processes, but that protection does not cover the vulnerable command construction prescribed by `SKILL.md`. ### Attack Path 1. An attacker sends a Telegram text message beginning with a recognized callback prefix, such as `tfb_preview_`. 2. The message appends shell syntax after the accepted prefix. 3. Following the Skill instructions, the agent treats the entire inbound message as callback data. 4. The agent concatenates that data into the `exec(command="...") ...[truncated 838 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not concatenate callback data into a shell command. 2. Invoke the dispatcher with an argument-array API where the callback is passed as a distinct argument, for example conceptually: ```python exec_argv([ "python3", dispatcher_path, "handle-callback", callback_data, ]) ``` 3. If only a command-string API is available, use a trusted argument-quoting function such as `shlex.quote`; argument-array execution remains preferable. 4. Validate the complete callback against anchored, action-specific formats before execution. Reject whitespace, shell metacharacters, control characters, and unexpected suffixes. 5. Do not use a prefix-only expression as the security boundary. Use full matching, bounded callback length, and explicit permitted character sets. 6. Update all examples in `SKILL.md` so agents are never instructed to interpolate inbound data into command strings. 7. Add tests containing command separators, substitutions, quotes, newlines, and redirections to confirm that malicious callback text is rejected or passed literally. ]]>
