T09 · Insecure Skill Coding Practices
- Location
INSTALLATION.md:371- Finding
Shell Command Injection in the OpenClaw Integration Example
- Content
View full analysis
{ exec(cmd, (error, stdout, stderr) => { ``` ### Technical Analysis The documented OpenClaw integration constructs a shell command by directly interpolating `instruction` and `options.location`, then passes the resulting string to `child_process.exec()`. `exec()` invokes the operating-system shell. Double quotes around interpolated values do not provide reliable command injection protection. An attacker can include shell syntax such as an embedded quote, command substitution, redirection, or command separators in either value. The shell will interpret that syntax before executing `human-rent`. This is particularly dangerous in an AI-agent integration because task instructions may originate from untrusted users, external documents, web content, or model-generated text. Following the documented example can therefore turn a normal physical-task request into arbitrary local command execution. ### Attack Path 1. A user or attacker supplies a crafted task instruction or location to an OpenClaw agent. 2. The integration passes the value to `dispatchHuman()` without shell-safe argument handling. 3. The value is inserted directly into the `cmd` shell string. 4. An embedded quote terminates the intended quoted argument. 5. Shell operators introduce an additional command. 6. `exec()` starts a shell and executes both the intended command and the injected command. 7. The injected process inherits the agent's operating-system privileges and environment, potentially including ZhenRent credential ...[truncated 885 chars]- Remediation
View remediation
{ execFile('human-rent', args, { shell: false }, (error, stdout, stderr) => { if (error) { reject(error); return; } const taskIdMatch = stdout.match(/Task ID: (\S+)/); if (taskIdMatch) { resolve(taskIdMatch[1]); } else { reject(new Error('Could not parse task ID')); } }); }); } ``` Additional hardening should include: 1. Explicitly keep `shell: false`. 2. Validate location length and format before invoking the CLI. 3. Apply reasonable maximum lengths to task instructions. 4. Use a direct JavaScript API rather than a subprocess where practical. 5. Avoid attempting to solve command injection through manual quote escaping. 6. Add automated tests containing quotes, semicolons, command substitutions, newlines, and redirection operators. 7. Warn integrators that all user-controlled values must be passed as discrete process arguments. ]]>
