Back to skill

Security audit

Taizi Claw Shell

Security checks for vulnerabilities and agentic risk

Overview

This skill openly provides shell access, but its implementation can run user-supplied input through the host shell outside the stated tmux boundary and relies on weak safety controls.

Review carefully before installing. This skill gives broad shell authority and should only be used in a tightly sandboxed environment with no sensitive files, credentials, or network access. The handler should be changed to call `tmux` with argument arrays rather than a shell string and should add real user approval or stricter command policy before it is trusted.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
handler.js:12
Finding

Host-Shell Command Injection Through Unsafe tmux Command Construction

Content
View full analysis

Vulnerability Details

File Location: handler.js, lines 12–14
Vulnerability Type: OS command injection
Risk Level: High

Vulnerable Code

js
function sendCommand(cmd) {
  const escaped = cmd.replace(/"/g, '\\"');
  execSync(`tmux send-keys -t claw "${escaped}" C-m`);
}

Technical Analysis

The cmd value is supplied by the caller and interpolated into a command string executed by execSync(). Node.js passes this string to a host shell. The implementation escapes only double-quote characters, which does not prevent shell evaluation of command substitutions such as $() or backticks.

Consequently, a crafted value can cause the host shell to execute commands while constructing the arguments for tmux. This execution occurs outside the designated tmux session and therefore violates the documented isolation expectation that commands are run inside session claw.

The isDangerous() substring denylist does not eliminate this vulnerability. It only detects a small set of literal strings and does not account for shell substitutions, alternate command syntax, variable expansion, encoding, or equivalent utilities. A payload containing a substitution that does not include one of the blocked substrings can reach sendCommand() and execute in the host shell.

Attack Path

  1. An attacker or untrusted caller invokes claw_shell_run with a crafted command containing shell substitution syntax, such as:
    sh
    echo $(touch /tmp/claw-shell-injection-proof)
    
  2. The command passes the denylist because it contains none of the listed blocked substrings.
  3. sendCommand() escapes only double quotes and interpolates the remaining input into:
    sh
    tmux send-keys -t claw "echo $(touch /tmp/claw-shell-injection-proof)" C-m
    
  4. The host shell evaluates $(touch /tmp/claw-shell-injection-proof) before tmux receives its arguments.
  5. The injected command executes direc ...[truncated 968 chars]
Remediation
View remediation

Remediation Suggestions

Do not construct shell command strings with caller-controlled input. Invoke tmux directly with an argument array and disable shell interpretation. Send the command as literal text and submit Enter separately, for example:

js
const { execFileSync } = require("node:child_process");

function sendCommand(cmd) {
  execFileSync("tmux", ["send-keys", "-t", "claw", "-l", "--", cmd], {
    shell: false
  });
  execFileSync("tmux", ["send-keys", "-t", "claw", "C-m"], {
    shell: false
  });
}

Additional hardening should include:

  1. Avoid using shell-backed execSync() for all fixed tmux operations; use execFileSync() or spawnSync() with fixed executable names and argument arrays.
  2. Treat substring denylisting as defense-in-depth only, not as an injection control.
  3. Implement explicit authorization state if dangerous commands are intended to run after user approval. The current API has no approval field and therefore cannot securely distinguish an approved request from an unapproved one.
  4. Apply an allowlist or a structured command policy if the tool does not require unrestricted shell access.
  5. Run the skill under a dedicated, least-privileged operating-system account with restricted filesystem, credential, and network access.
  6. Add regression tests using $(), backticks, quotes, newlines, semicolons, pipes, redirections, and variable expansion to verify that input reaches tmux literally and is never evaluated by the host shell.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This skill executes arbitrary user-supplied shell commands by forwarding them into a persistent tmux shell session, but it provides only a weak substring-based blocklist and no meaningful safety boundary or clear user-facing disclosure of the risks. The blocklist is trivially bypassed, the command is still interpreted by a shell-like environment inside tmux, and the persistent session increases the chance of unintended stateful or chained harmful actions.

Content

No source excerpt is available for this finding.