T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:86
- Finding
- Shell Command Injection Through Unquoted User-Controlled Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 86–92 **Vulnerability Type**: Shell command injection caused by unsafe argument interpolation **Risk Level**: High ### Vulnerable Code ```markdown **Triggers:** "check arb for [tokenA] and [tokenB]", "is there arb between [tokenA] and [tokenB]" ```bash cd ~/.openclaw/skills/citrea-claw-skill && node index.js arb:check <tokenA> <tokenB> ``` Example: user says "check arb for wcBTC and USDC" → run: ```bash cd ~/.openclaw/skills/citrea-claw-skill && node index.js arb:check wcBTC USDC.e ``` ``` The same unsafe construction pattern appears in other command templates, including `price`, `pool:price`, `pool:liquidity`, `balance`, and `txns`. ### Technical Analysis The Skill instructs the agent to build shell command strings by inserting token symbols, addresses, or other values derived from user messages. These arguments are not quoted or validated before being placed into commands executed through the `exec` tool. Although the JavaScript command handlers perform some validation, that validation occurs only after the shell has parsed the command line. Shell metacharacters such as command separators, substitutions, pipes, or redirections can therefore be interpreted before `index.js` receives its arguments. The issue exceeds the minimum privileges required by the declared functionality. Reading public Citrea data requires only launching Node.js with fixed command names and validated data arguments; it does not require passing user-controlled text through a command shell. ### Attack Path 1. A user invokes a supported Skill trigger and supplies a malicious token or address argument containing shell syntax. 2. The agent follows `SKILL.md` and interpolates that value into the documented command string. 3. The `exec` tool invokes the command through a shell. 4. The shell interprets the injected syntax independently of the intended `node index.js` command. 5. The injected command runs with the ...[truncated 752 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not construct a shell command by concatenating user-controlled text. 2. Use a process-execution API that accepts an executable and argument array without invoking a shell, for example: ```js spawn('node', ['index.js', 'arb:check', tokenA, tokenB], { shell: false, stdio: 'inherit' }) ``` 3. Strictly allowlist token arguments against the supported token registry before execution. 4. Validate addresses with a complete hexadecimal-address pattern: ```regex ^0x[0-9a-fA-F]{40}$ ``` 5. Validate numeric arguments using explicit minimum and maximum bounds. 6. If the OpenClaw execution interface only supports command strings, apply robust shell quoting to every argument after validation. Validation must occur before constructing the command. 7. Update `SKILL.md` to explicitly prohibit direct interpolation of raw user text into shell commands. 8. Run the Skill under a dedicated, minimally privileged account with no access to unrelated files or credentials. ]]>
