T09 · Insecure Skill Coding Practices
- Location
handler.js:10- Finding
Host Shell Command Injection Through Unsafe Command Interpolation
- Content
View full analysis
Vulnerability Details
File Location:
handler.js, lines 10-13
Vulnerability Type: OS command injection
Risk Level: HighVulnerable Code
js function sendCommand(cmd) { const escaped = cmd.replace(/"/g, '\\"'); execSync(`tmux send-keys -t claw "${escaped}" C-m`); }Technical Analysis
The attacker-controlled
cmdvalue is interpolated into a command string passed toexecSync. By default,execSyncexecutes string commands through a system shell.Escaping only double quotation marks does not prevent shell evaluation inside double-quoted strings. Shell command substitutions using
$(...)or backticks remain active and are evaluated by the host shell beforetmuxis invoked. Crafted backslash and quotation-mark sequences may also interfere with the intended quoting.This behavior violates the documented guarantee that commands are run inside the dedicated
clawtmux session. Injected command substitutions execute directly in the environment of the Node.js skill process rather than in the tmux session.Attack Path
-
An attacker supplies a command containing shell substitution, for example:
sh echo "$(touch /tmp/claw-shell-injected)" -
The value does not contain any substring rejected by
isDangerous. -
sendCommandescapes double quotation marks but leaves$()active. -
The resulting command is passed to the host shell by
execSync. -
The host shell executes
touch /tmp/claw-shell-injectedbefore invokingtmux. -
More consequential commands can be substituted to read, alter, or destroy resources available to the skill process.
Impact Assessment
An attacker able to control the
commandinput can execute arbitrary operating-system commands with the user identity and privileges of the Node.js process. This can provide access to all files, credentials, environment variables, processes, and network resources available to that accou ...[truncated 273 chars]-
- Remediation
View remediation
Remediation Suggestions
Do not construct a shell command by interpolating untrusted text. Invoke
tmuxdirectly with a fixed executable and an argument array while disabling shell processing. For example:js const { execFileSync } = require("node:child_process"); function sendCommand(cmd) { execFileSync( "tmux", ["send-keys", "-t", "claw", "--", cmd, "C-m"], { shell: false, stdio: "ignore" } ); }Additional hardening should include:
- Reject NUL bytes and unexpected control characters in
cmd. - Use fixed argument arrays for every
tmuxinvocation, including session creation and output capture. - Run the skill under a dedicated, unprivileged operating-system account.
- Restrict that account's filesystem and network access using sandboxing or container controls.
- Add regression tests containing
$(), backticks, nested quotes, backslashes, semicolons, and newlines, verifying that no command is evaluated by the host shell.
- Reject NUL bytes and unexpected control characters in
