Back to skill

Security audit

Openclaw Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real local sandboxed command runner, but its safety claims are overstated and its command-execution service is under-scoped.

Review before installing. This skill may be useful if you intentionally want a local Bubblewrap-backed command runner, but do not rely on its current claims of validation, confirmation, loop limiting, or strict read-only isolation. Run it only in a narrow project directory, avoid sensitive working directories, and prefer a release with pinned dependencies, workspace-bound writable mounts, authentication or strict socket permissions, and execution resource limits.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skillshieldd/src/sandbox.rs:52
Finding

Arbitrary Host Directory Is Mounted Read-Write Inside the Sandbox

Content
View full analysis
, Json(payload): Json, ) -> Json { let request = ActionRequest { request_id: "exec".into(), session_id: "exec".into(), timestamp: timestamp_now(), actor: Actor { agent_name: "skillshield-wrapper".into(), tool_name: Some("skillshield-exec.sh".into()), run_id: None, }, action: Action::ShellExec(ShellExecAction { command: payload.command.clone(), args: vec![], env_diff: vec![], }), context: RequestContext { cwd: payload.cwd.clone(), workspace_root: payload.cwd.clone(), requires_approval: false, }, }; let decision = policy::evaluate(&request); let executor_name = state.executor.name().to_string(); match decision.execution_plan { models::ExecutionPlan::Execute | models::ExecutionPlan::Sandbox => { match state .executor .execute_shell(&payload.command, payload.cwd.as_deref()) .await ``` `skillshieldd/src/sandbox.rs:52-55`: ```rust if let Some(dir) = working_dir { cmd.arg("--bind").arg(dir).arg(dir); cmd.current_dir(dir); } ``` ### Technic ...[truncated 2237 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skillshieldd/src/policy.rs:9
Finding

Shell Policy Performs No Command Validation and Labels Every Command Low Risk

Content
View full analysis
InterceptResponse { match &request.action { Action::ShellExec(_) => response( ExecutionPlan::Sandbox, Effect::Sandbox, RiskLevel::Low, "shell.sandbox", "Shell command will run inside the Bubblewrap sandbox".to_string(), ), ``` `skillshieldd/src/main.rs:118-131`: ```rust let decision = policy::evaluate(&request); let executor_name = state.executor.name().to_string(); match decision.execution_plan { models::ExecutionPlan::Execute | models::ExecutionPlan::Sandbox => { match state .executor .execute_shell(&payload.command, payload.cwd.as_deref()) .await { ``` ### Technical Analysis The policy matches only the action type and ignores the shell command's contents. Every shell command receives the same `Sandbox`, `Low` risk decision. The evaluator does not inspect commands, arguments, shell operators, target paths, actor identity, environment changes, workspace boundaries, or approval requirements. Consequently, destructive commands, persistence-related commands, fork bombs, and commands targeting the writable host bind mount are treated identically to harmless commands such as `echo`. The execute handler immediately runs any command receiving the `Sandbox` decision. The shell is intentionally invoked through `sh -c`, so shell metacharacters and compound commands are expected to execute. The defect is not shell parsing by itself; it is the absence of the validation and approval policy that the component claims to provide. ### Attack Path 1. An attacker supplies a destructive or otherwise high-risk shell com ...[truncated 1017 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skillshieldd/src/sandbox.rs:57
Finding

Sandbox Execution Has No Timeout or Resource Limits

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
skillshield-exec.sh:48
Finding

First-Run Build Uses Unlocked Third-Party Dependency Resolution

Content
View full analysis
&2 CARGO_TARGET_DIR="$TARGET_DIR" cargo build --release --manifest-path "$MANIFEST_PATH" >&2 stop_daemon fi ``` `skillshieldd/Cargo.toml:8-19`: ```toml [dependencies] anyhow = "1" async-trait = "0.1.89" axum = { version = "0.7", features = ["macros", "json"] } hyper = { version = "1.8.1", features = ["full"] } hyper-util = { version = "0.1.20", features = ["tokio", "server", "server-auto"] } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal", "net", "process"] } tower = { version = "0.5.3", features = ["util"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } ``` `SKILL.md:24`: ```bash npx clawhub@latest install skillshield-openclaw ``` ### Technical Analysis The supplied project structure contains no `Cargo.lock`, while the manifest permits dependency versions through semver ranges. The wrapper invokes `cargo build` without `--locked`, allowing Cargo to resolve and download dependency versions available at build time. Rust dependencies can contain build scripts or proc macros that execute during compilation. Therefore, the effective code executed during the first build is not completely represented by the reviewed files and can change as compatible dependency releases are published. The installation documentation also invokes `npx clawhub@latest`, which intentionally retrieves the current release rather than a fixed, reviewed version. This is not evidence that any listed dependency is malicious, but it cr ...[truncated 1175 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims strict shell sandboxing with Bubblewrap, but the analyzed content does not substantiate that boundary and suggests broader file and network decision capabilities. This mismatch is dangerous because users and agents may over-trust the skill's safety guarantees and permit sensitive operations under a false assumption of isolation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill advertises and appears to enable shell, environment, and network-capable behavior, but it declares no explicit permission or allowed-tool scope. That creates an authorization gap where an agent or user may assume the skill is narrowly constrained when it is not, increasing the chance of unintended command execution or data exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

Using npx clawhub@latest install ... pulls and executes an unpinned package version, which introduces supply-chain risk. If the upstream package is compromised or changes behavior, users may run attacker-controlled install logic with the skill's trust context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · skillshield-exec.sh (reported line 60)May include surrounding context.

sh
fi

daemon_healthy() {
    curl -fsS --unix-socket "$SOCKET_PATH" http://localhost/health 2>/dev/null
}

start_daemon() {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script packages a user-supplied command and submits it to the local execution daemon, which results in shell-command execution. While the file logs daemon startup/build events, it does not clearly disclose to the user that the provided command will be executed, nor does it prompt for confirmation at the execution point.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · skillshieldd/src/main.rs (reported line 8)May include surrounding context.

rust
use std::sync::Arc;
#[cfg(unix)]
use tokio::net::UnixListener;
use tokio::net::TcpListener;

use anyhow::Context;
use axum::{extract::State, routing::{get, post}, Json, Router};

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · skillshieldd/src/main.rs (reported line 79)May include surrounding context.

rust
use std::sync::Arc;
#[cfg(unix)]
use tokio::net::UnixListener;
use tokio::net::TcpListener;

use anyhow::Context;
use axum::{extract::State, routing::{get, post}, Json, Router};

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The /v1/execute endpoint accepts a command from the request body and executes it server-side after only an internal policy check, with no authentication, authorization, or user-consent mechanism visible in this file. In the context of an agent skill exposing command execution as a network service, this creates a remote command execution surface that can be abused by any party able to reach the socket or TCP listener.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The code executes a provided command string via sh -c inside bubblewrap, which is a safety-relevant subprocess operation. Although the sandbox behavior is documented in comments, there is no user-facing confirmation, logging, or disclosure at the execution site that a shell command is being run.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The startup path unconditionally removes the configured Unix socket file with std::fs::remove_file(path) before binding. This is a file-deletion operation, and this file contains no visible warning comment or user-facing disclosure explaining that startup may delete an existing filesystem entry at that path.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.