Back to skill

Security audit

Claw Shell 1.0.0

Security checks for vulnerabilities and agentic risk

Overview

This skill openly provides shell access through tmux, but its safety boundary is weak and can let commands run in broader or less visible ways than users would expect.

Install only if you intentionally want a broad shell-control skill and can run it inside a tightly sandboxed environment. Do not treat its dangerous-command warning as a reliable safety control, and avoid using it where the runtime account can access sensitive files, credentials, long-lived sessions, or important system state.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
handler.js:10
Finding
Shell Injection Allows Command Execution Outside the Intended tmux Session<![CDATA[ ## Vulnerability Details **File Location**: `handler.js`, lines 10–13 **Vulnerability Type**: OS command injection through unsafe shell-string construction **Risk Level**: High ### Vulnerable Code ```javascript function sendCommand(cmd) { const escaped = cmd.replace(/"/g, '\\"'); execSync(`tmux send-keys -t claw "${escaped}" C-m`); } ``` ### Technical Analysis The attacker-controlled `cmd` value is interpolated into a command string passed to `execSync()`. Node.js executes this string through a system shell. Escaping only double quotation marks does not neutralize shell syntax that remains active inside a double-quoted shell argument. In particular, command substitutions using `$(...)` or backticks are evaluated by the parent shell before `tmux` receives the text. Consequently, an input intended to be typed inside tmux can cause an additional command to execute directly in the Skill handler's process context. This violates the documented security boundary that commands are always run inside tmux session `claw`. ### Attack Path 1. An attacker or untrusted caller supplies a command containing shell substitution, for example: ```text echo $(id > /tmp/claw-shell-proof) ``` 2. `isDangerous()` does not reject the input because it contains none of the denylisted strings. 3. `sendCommand()` interpolates the input into the shell command: ```text tmux send-keys -t claw "echo $(id > /tmp/claw-shell-proof)" C-m ``` 4. The shell launched by `execSync()` evaluates `$(id > /tmp/claw-shell-proof)` before invoking `tmux`. 5. The injected `id` command therefore runs outside tmux with the identity and permissions of the Skill process. 6. Only the resulting substituted text is passed to the tmux pane, which can make the out-of-session execution less apparent in captured output. ### Impact Assessment An attacker can execute arbitrary shell commands in the host context of the Skill handler rather than only inside the designated tmux ses ...[truncated 495 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Avoid invoking a shell when passing attacker-controlled command text to `tmux`. Use an API that accepts the executable and arguments separately, such as `execFileSync()` or `spawnSync()` with shell processing disabled: ```javascript const { execFileSync } = require("node:child_process"); function sendCommand(cmd) { execFileSync("tmux", [ "send-keys", "-t", "claw", "--", cmd, "C-m" ], { shell: false }); } ``` Apply the same argument-array pattern to all `tmux` operations for defense in depth. Additionally: - Run the Skill under a dedicated, minimally privileged operating-system account. - Restrict filesystem and network access through sandboxing or container isolation. - Validate the input type and enforce reasonable command-length and resource limits. - Add regression tests using inputs containing `$()`, backticks, quotes, semicolons, newlines, and shell redirections. - Verify that test payloads are delivered literally to tmux and never evaluated by the handler's parent shell. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
handler.js:24
Finding
Bypassable Denylist Fails to Enforce Destructive-Command Approval<![CDATA[ ## Vulnerability Details **File Location**: `handler.js`, lines 24–44 **Vulnerability Type**: Insufficient command validation and missing trusted approval mechanism **Risk Level**: Medium ### Vulnerable Code ```javascript function isDangerous(cmd) { const bad = ["sudo", " rm ", " rm-", "reboot", "shutdown", "mkfs", "dd "]; const lower = ` ${cmd.toLowerCase()} `; return bad.some(k => lower.includes(k)); } // MAIN ENTRYPOINT // OpenClaw will call this function when using the skill tool async function claw_shell_run(input) { const { command } = input; if (!command || typeof command !== "string") { return { error: "command is required" }; } if (isDangerous(command)) { return { error: "dangerous_command", message: `Command looks dangerous. Ask the user for explicit approval before running: ${command}` }; } ``` ### Technical Analysis The safety control relies on matching a short set of literal substrings. This does not determine the semantic effect of an arbitrary shell command. The same destructive operation can be performed using: - Utilities not included in the denylist. - Language interpreters such as Python, Perl, or Node.js. - Shell functions, aliases, variables, or expansion. - Alternative whitespace and command construction. - Indirect scripts or binaries. For example, a file can be removed with `unlink`, and directory trees can be deleted through an interpreter without including the literal substring ` rm `. Such commands pass `isDangerous()` unchanged. The documentation also states that dangerous commands should require explicit user approval, but the handler accepts no approval field or trusted authorization state. A matching command is always rejected, while a semantically equivalent non-matching command is executed without approval. Therefore, neither side of the documented confirmation workflow is securely implemented. ### Attack Path 1. An attacker chooses a destructive operation that does n ...[truncated 1273 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not treat a command denylist as a security boundary for an arbitrary shell interface. Recommended hardening measures include: 1. **Implement trusted two-stage authorization** - Return a stable identifier and normalized command when confirmation is required. - Require a short-lived, cryptographically protected approval token generated by trusted application code. - Bind the token to the exact command, requesting user, tmux session, and expiration time. - Never accept a caller-provided Boolean such as `approved: true` as sufficient proof. 2. **Prefer an allowlist** - If the business purpose permits, expose structured operations rather than arbitrary command strings. - Allow only known executables and validated argument forms. - Reject shell operators and interpreter-based execution where they are not necessary. 3. **Use operating-system isolation** - Run the tmux session under a dedicated account with minimal permissions. - Use a sandbox or container with read-only mounts where possible. - Restrict sensitive filesystem paths, network access, process capabilities, and resource consumption. 4. **Align implementation and documentation** - Either implement the documented approval workflow or explicitly state that dangerous operations are unsupported. - Ensure approval is evaluated by trusted orchestration code rather than inferred from command text. 5. **Add adversarial tests** - Test alternative deletion tools, interpreters, shell expansion, aliases, unusual whitespace, scripts, and indirect execution. - Confirm that semantically dangerous operations cannot bypass the selected authorization model. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The skill accepts an arbitrary string from input.command and sends it into a persistent tmux shell session, effectively providing broad shell execution capability. With no constrained command set, no authentication/authorization checks, and no clear justified purpose in the file, this can be abused to run destructive commands, access local data, install persistence, or pivot further in the environment.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The code claims that only 'dangerous' commands need explicit approval, but its check is just a small substring blacklist that is trivial to bypass and misses many harmful operations. An attacker can execute arbitrary commands such as data exfiltration, file modification, process control, network access, or obfuscated destructive commands without triggering the warning, creating a misleading and unsafe trust boundary.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill executes the provided command and manipulates a tmux session without any built-in user-facing disclosure or confirmation at the point of execution. In an agent setting, this reduces transparency and can cause users or higher-level components to underestimate that commands are being run on the host, increasing the chance of unsafe or unintended execution.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
handler.js:5