T09 · Insecure Skill Coding Practices
Error
- Location
- plugin.ts:217
- Finding
- Shell Command Injection Through the Download Directory Parameter<![CDATA[ ## Vulnerability Details **File Location**: `plugin.ts`, lines 217-226 **Vulnerability Type**: OS command injection through unsafe shell interpolation **Risk Level**: Critical ### Vulnerable Code ```typescript const cmd = `nohup aria2c --enable-rpc --rpc-listen-all \ ${dhtArgs} \ --dir="${downloadDir}" \ --seed-ratio=${seedRatio} \ --seed-time=${seedTime} \ --bt-max-peers=50 \ --bt-seed-unverified=true \ > /tmp/aria2-rpc.log 2>&1 &`; exec(cmd, (err2) => { ``` ### Technical Analysis The `downloadDir` value can be supplied through the `bt_start_rpc` tool and is interpolated directly into a command string executed by `child_process.exec`. Although it is surrounded by double quotes, the value is not escaped or validated. Because `exec` invokes the command through a shell, a malicious value containing a double quote followed by shell metacharacters can terminate the `--dir` argument and append another command. Quoting the interpolated value is therefore insufficient to prevent command injection. The vulnerable operation runs with the same operating-system privileges as the plugin host. The input schema does not provide a security boundary and cannot replace contextual shell escaping or shell-free process execution. ### Attack Path 1. An attacker or untrusted agent invocation calls `bt_start_rpc`. 2. The attacker supplies a crafted `downloadDir` containing a closing quote and shell syntax. 3. The handler inserts the value into the `cmd` template without validation or escaping. 4. `child_process.exec` passes the resulting string to the operating-system shell. 5. The shell interprets the injected metacharacters and executes the appended command. 6. The injected command runs with the privileges of the OpenClaw/plugin process. ### Impact Assessment Successful exploitation permits arbitrary command execution under the plugin process's user account. Depending on that account's permissions, an attacker could: - Read, modify, or delete fi ...[truncated 554 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Replace `child_process.exec` with `spawn` or `execFile` and supply every aria2 option as a distinct argument, without invoking a shell. For example: ```typescript import { spawn } from "child_process"; const argumentsList = [ "--enable-rpc", "--no-rpc-listen-all", `--dir=${downloadDir}`, `--seed-ratio=${seedRatio}`, `--seed-time=${seedTime}`, "--bt-max-peers=50", "--bt-seed-unverified=true", ]; if (enableDht) { argumentsList.push("--enable-dht", "--enable-dht6"); } const child = spawn("aria2c", argumentsList, { detached: true, stdio: "ignore", }); child.unref(); ``` Additional hardening should include: 1. Require `downloadDir` to be an absolute filesystem path. 2. Resolve and normalize the path before use. 3. Restrict downloads to an explicitly approved base directory where appropriate. 4. Reject null bytes and paths that escape the approved directory. 5. Validate `seedRatio` and `seedTime` as finite numbers within safe ranges. 6. Do not implement shell redirection in a command string; configure `stdio` using Node.js process APIs. 7. Run aria2 and the plugin under a dedicated, unprivileged account with restricted filesystem access. ]]>
