T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/shared/utils.js:108
- Finding
- Shell Command Injection Through the Message Recipient<![CDATA[ ## Vulnerability Details **File Location**: `scripts/shared/utils.js:108-111`, invoked from `scripts/signChallenge.js:82` and `scripts/linkHumanToAgent.js:126` **Vulnerability Type**: OS command injection **Risk Level**: Critical ### Vulnerable Code ```js function sendDirectMessage(target, message) { const { execSync } = require("child_process"); execSync(`openclaw message send --target ${target} --message "${message}"`); } ``` The vulnerable function is called with command-line data: ```js sendDirectMessage(args.to, codeFormating(tokenString)); ``` ```js sendDirectMessage(args.to, urlFormating(verificationMessage, url)); ``` ### Technical Analysis `sendDirectMessage()` constructs a shell command by directly interpolating the dynamic `target` and `message` values into a string passed to `child_process.execSync()`. The `target` value originates from the `--to` command-line argument and is not validated, escaped, or safely quoted. Because `execSync()` executes through a shell, an attacker can include shell control characters such as semicolons, pipes, redirections, command substitutions, or logical operators in the recipient value. The `message` value is also interpolated into a double-quoted shell string. If dynamic message content contains shell-significant syntax, it may provide an additional injection surface. Shell invocation is not necessary for the declared functionality. The Skill only needs to invoke the `openclaw` executable with a fixed set of arguments, so this implementation exceeds the minimum execution privilege required. ### Attack Path 1. An attacker supplies or influences the sender identifier used as the `--to` argument. 2. The Agent runs either `signChallenge.js` or `linkHumanToAgent.js` with that attacker-controlled value. 3. The script passes `args.to` to `sendDirectMessage()`. 4. `sendDirectMessage()` concatenates the value into a shell command. 5. Shell metacharacters terminate or modify the intended `openclaw` c ...[truncated 1015 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Eliminate shell-string construction. Invoke the executable directly with a structured argument array: ```js function sendDirectMessage(target, message) { const { execFileSync } = require("child_process"); execFileSync( "openclaw", ["message", "send", "--target", target, "--message", message], { stdio: "inherit", shell: false, }, ); } ``` Additional hardening should include: 1. Validate `target` against the exact documented identifier format using an allowlist expression. 2. Apply reasonable length limits to both `target` and `message`. 3. Reject control characters, null bytes, and unexpected line breaks. 4. Do not attempt to fix the issue with ad hoc shell escaping; avoid the shell entirely. 5. Add automated tests using values containing semicolons, quotes, command substitution, pipes, and redirection operators. 6. Run the Skill under a restricted account with no unnecessary filesystem or system privileges. ]]>
