Back to skill

Security audit

Skill Sandbox

Security checks for vulnerabilities and agentic risk

Overview

This security helper is not clearly malicious, but its installer can automatically replace live skills and has path-handling flaws that could affect files outside the intended skill folders.

Treat this as a Review install. Only use it in a disposable or backed-up OpenClaw workspace, avoid `--force`, `--promote`, and custom live/staging directories unless you have manually verified the exact staged contents, and prefer a fixed version that validates skill names, canonicalizes paths, records scan hashes, and asks before replacing live skills.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skill-sandbox.sh:108
Finding
Path Traversal Enables Destructive Filesystem Operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skill-sandbox.sh`, lines 64-84, 108-109, 118-131, and 145-146 **Vulnerability Type**: Path traversal leading to arbitrary directory deletion or movement **Risk Level**: High ### Vulnerable Code ```bash while [[ $# -gt 0 ]]; do case "$1" in --force) FORCE_FLAG="--force"; shift ;; --version) VERSION_FLAG="--version $2"; shift 2 ;; --promote) PROMOTE_ONLY=true; shift ;; --scan-only) SCAN_ONLY=true; shift ;; --list-staged) LIST_STAGED=true; shift ;; --staging-dir) STAGING_DIR="$2"; shift 2 ;; --live-dir) LIVE_DIR="$2"; shift 2 ;; --help|-h) usage ;; -*) echo "Unknown option: $1"; usage ;; *) if [[ -z "$SKILL_NAME" ]]; then SKILL_NAME="$1" else echo "Unexpected argument: $1"; usage fi shift ;; esac done STAGED_PATH="$STAGING_DIR/$SKILL_NAME" LIVE_PATH="$LIVE_DIR/$SKILL_NAME" if $PROMOTE_ONLY; then if [[ ! -d "$STAGED_PATH" ]]; then echo -e "${RED}✗ Skill '$SKILL_NAME' not found in staging ($STAGING_DIR)${NC}" exit 1 fi if [[ -d "$LIVE_PATH" ]]; then echo -e "${YELLOW}⚠ Replacing existing live skill '$SKILL_NAME'${NC}" rm -rf "$LIVE_PATH" fi mv "$STAGED_PATH" "$LIVE_PATH" echo -e "${GREEN}✅ Promoted '$SKILL_NAME' → $LIVE_PATH${NC}" exit 0 fi # Clean previous staged version [[ -d "$STAGED_PATH" ]] && rm -rf "$STAGED_PATH" ``` ### Technical Analysis `SKILL_NAME` is accepted without validating that it is a single safe directory name. Values containing path separators or traversal components such as `..` are appended directly to `STAGING_DIR` and `LIVE_DIR`. Shell quoting prevents token splitting and shell metacharacter injection, but it does not prevent filesystem path traversal. The resulting paths are subsequently passed to high-impact operations including `rm -rf` and `mv`. The script neither canonicalizes these paths nor verifies that they remain immediate children of the intended stag ...[truncated 1489 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce a strict Skill-name allowlist before constructing any path: ```bash if [[ ! "$SKILL_NAME" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] || [[ "$SKILL_NAME" == "." || "$SKILL_NAME" == ".." ]]; then echo "Invalid skill name" >&2 exit 1 fi ``` 2. Explicitly reject `/`, backslashes, control characters, and traversal components. 3. Canonicalize the parent directories with `realpath` before destructive operations. 4. Verify that each resolved target is an immediate child of the expected canonical parent: ```bash staging_root=$(realpath -m -- "$STAGING_DIR") staged_path=$(realpath -m -- "$STAGING_DIR/$SKILL_NAME") if [[ "$(dirname -- "$staged_path")" != "$staging_root" ]]; then echo "Staged path escapes staging root" >&2 exit 1 fi ``` 5. Apply equivalent containment checks to `LIVE_PATH`. 6. Reject dangerous custom roots, including empty values, `/`, the user's home directory, and the workspace root where inappropriate. 7. Before `rm -rf`, require that the target is nonempty, canonicalized, contained beneath the expected root, and not equal to the root itself. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skill-sandbox.sh:374
Finding
Incomplete Blacklist Scanner Can Automatically Promote Malicious Skills<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skill-sandbox.sh`, lines 219-270 and 374-388 **Vulnerability Type**: Security-control bypass caused by incomplete static detection and unsafe automatic promotion **Risk Level**: High ### Vulnerable Code ```bash # eval / dynamic execution EVAL_HITS=$(grep_code 'eval\s*(') if [[ -n "$EVAL_HITS" ]]; then finding "CRITICAL" "eval() calls:" show_matches "$EVAL_HITS" fi FUNC_HITS=$(grep_code 'new Function\|Function(') if [[ -n "$FUNC_HITS" ]]; then finding "CRITICAL" "Dynamic Function() constructor:" show_matches "$FUNC_HITS" fi # Network calls NET_HITS=$(grep_code 'fetch(\|axios\|http\.\(get\|post\|request\)\|https\.\(get\|post\|request\)\|urllib\|requests\.\(get\|post\)\|XMLHttpRequest\|\.ajax(') CURL_HITS=$(grep_code 'curl \|wget ') # Shell execution EXEC_HITS=$(grep_code 'child_process\|execSync\|spawnSync\|\.exec(\|\.spawn(\|subprocess\.\|os\.system(\|os\.popen(') # Environment / secret access ENV_HITS=$(grep_code 'process\.env\|os\.environ\|os\.getenv\|API_KEY\|SECRET_KEY\|PRIVATE_KEY\|PASSWORD\|CREDENTIAL\|ACCESS_TOKEN') # Base64 / obfuscation B64_HITS=$(grep_code 'atob(\|btoa(\|Buffer\.from.*base64\|b64decode\|b64encode') ``` ```bash if [[ $CRITICALS -gt 0 ]]; then echo "VERDICT:FAIL" exit 2 elif [[ $WARNINGS -gt 0 ]]; then echo "VERDICT:WARN" exit 0 else echo -e "${GREEN}${BOLD}✅ PASS — Clean. Auto-promoting to live.${NC}" if [[ -d "$LIVE_PATH" ]]; then rm -rf "$LIVE_PATH" fi mv "$STAGED_PATH" "$LIVE_PATH" echo -e " Installed: ${GREEN}$LIVE_PATH${NC}" echo "" echo "VERDICT:PASS" exit 0 fi ``` ### Technical Analysis The scanner treats the absence of matches from a limited set of regular expressions as proof that a downloaded Skill is clean. It then automatically moves that untrusted Skill into the live directory. The checks omit common shell execution and obfuscation forms, including: - `eval "$payload"` because the pattern requires an opening pare ...[truncated 2200 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not automatically promote untrusted executable Skills solely because blacklist scans produce zero matches. 2. Require explicit human or policy-engine approval before moving downloaded code into the live directory. 3. Treat unknown executable code as untrusted by default and run it only within a genuine operating-system sandbox with: - no inherited secrets; - restricted filesystem access; - disabled or allowlisted network access; - resource limits; - an unprivileged user identity. 4. Use language-aware parsers and established static-analysis tools instead of relying exclusively on `grep`. 5. Expand shell analysis to cover `eval`, `source`, dot-sourcing, command substitution, interpreter `-c` arguments, decoding utilities, pipelines, and indirect execution. 6. Inspect every executable or interpretable file type rather than only the current extension allowlist. 7. Verify package provenance, immutable version digests, signatures, publisher identity, and expected file manifests. 8. Distinguish “no pattern detected” from “verified safe”; use a neutral `UNVERIFIED` verdict for the former. 9. Preserve the staged package for review and record cryptographic hashes so reviewed content cannot be replaced before promotion. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/skill-sandbox.sh:69
Finding
Unquoted Version Expansion Allows Command-Line Argument Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skill-sandbox.sh`, lines 69 and 150 **Vulnerability Type**: Command-line argument injection through unsafe shell word expansion **Risk Level**: Medium ### Vulnerable Code ```bash --version) VERSION_FLAG="--version $2"; shift 2 ;; ``` ```bash # shellcheck disable=SC2086 if ! clawhub install "$SKILL_NAME" --dir "$STAGING_DIR" $FORCE_FLAG $VERSION_FLAG 2>&1; then echo -e "${RED}✗ clawhub install failed${NC}" exit 1 fi ``` ### Technical Analysis The value following `--version` is concatenated into the `VERSION_FLAG` string and subsequently expanded without quotation. Bash therefore applies word splitting and pathname expansion to the combined string. A crafted version value containing spaces can become multiple arguments to the `clawhub` command. If those arguments correspond to options supported by `clawhub`, the attacker may alter installer behavior beyond selecting a package version. Wildcard characters may also expand to local filenames. This is not direct shell-command injection: shell metacharacters introduced through variable expansion are not reparsed as shell syntax. However, it is command-line argument injection into the invoked `clawhub` process. The argument parser also reads `$2` without first checking that a value exists. Under `set -u`, a missing value can terminate the script unexpectedly, creating a reliability issue. ### Attack Path 1. An attacker controls or influences the version string supplied by a user or automated Agent. 2. The attacker supplies a value containing whitespace followed by additional `clawhub` arguments. 3. The script stores the complete value in `VERSION_FLAG`. 4. Unquoted expansion splits the value into multiple command-line words. 5. `clawhub install` receives attacker-selected options in addition to the intended `--version` option. 6. The resulting effect depends on the options supported by the installed `clawhub` version, but may modify installatio ...[truncated 546 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store command arguments in a Bash array rather than a string: ```bash CL AWHUB_ARGS=() # During parsing: --version) [[ $# -ge 2 ]] || { echo "--version requires a value" >&2 exit 1 } CLAWHUB_ARGS+=(--version "$2") shift 2 ;; --force) CLAWHUB_ARGS+=(--force) shift ;; ``` Use a correctly named array in production, for example: ```bash clawhub_args=() clawhub_args+=(--version "$2") clawhub install "$SKILL_NAME" --dir "$STAGING_DIR" "${clawhub_args[@]}" ``` 2. Validate versions against the format accepted by ClawHub, preferably a strict semantic-version pattern. 3. Reject version values beginning with `-` or containing whitespace when those forms are not explicitly supported. 4. Validate that every option requiring a value has a following argument before accessing `$2`. 5. Remove the ShellCheck suppression after converting the command to safe array-based invocation. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
warnings only) → quarantined, manual review recommended
   - ❌ **FAIL** (critical findings) → quarantined, deep audit required

## Scan Details

### Critical Findings (auto-quarantine)
- `eval()`, `new Function()` — dynamic code execution
- Symlinks — path traversal risk
- `postinstall` / `preinstall` scripts in package.json — npm supply chain vector
- Dangerous SKILL.md instructions (disable security, exfiltrate, reverse shells, chmod 777)

### Warning Findings (review recommended)
- Network calls (`fetch`, `curl`, `axios`, `http`)
- Shell execution (`child_process`, `exec`, `spawn`, `subprocess`)
- Environment/secret access (`process.env`, `API_KEY`, `TOKEN`)
- Base64 encoding patterns (potential obfuscation)
- File system writes
- Hidden files (excluding `.clawhub/`)
- Non-text binary files

## Integration with Agent Workflows

For teams using security auditor agents (like Sentinel), the recommended flow:

1. Run `skill-sandbox.sh` for the fast automated scan
2. If WARN
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Intent-Code Divergence

High
Confidence
95% confidence
Finding
The script advertises a sandboxed security-scanning installation flow, but the documented `--promote` mode explicitly bypasses scanning and moves staged content directly into the live skills directory. This creates a trust-boundary bypass: any staged skill, including one staged before fixes or one modified after staging, can be promoted without revalidation.

Intent-Code Divergence

High
Confidence
96% confidence
Finding
The usage text confirms that `--promote` skips the scan phase, which undermines the core security promise of the skill-sandbox tool. In a supply-chain defense tool, allowing a documented bypass materially weakens the control because users may treat promotion as inherently safe.

Chaining Abuse

High
Category
Tool Misuse
Content
fi

  # Clean previous staged version
  [[ -d "$STAGED_PATH" ]] && rm -rf "$STAGED_PATH"

  echo -e "${CYAN}📦 Installing '$SKILL_NAME' to staging...${NC}"
  # shellcheck disable=SC2086
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SKILL_MD="$STAGED_PATH/SKILL.md"
if [[ -f "$SKILL_MD" ]]; then
  DANGER=$(grep -in \
    "disable.*security\|ignore.*guardrail\|skip.*auth\|exfiltrate\|phone.home\|send.*to.*server\|upload.*data\|rm -rf /\|delete.*all\|chmod 777\|0\.0\.0\.0\|mkfifo\|nc -l\|reverse.shell\|>/etc/\|curl.*|.*bash\|wget.*|.*sh" \
    "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$DANGER" ]]; then
    finding "CRITICAL" "Dangerous instructions in SKILL.md:"
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SKILL_MD="$STAGED_PATH/SKILL.md"
if [[ -f "$SKILL_MD" ]]; then
  DANGER=$(grep -in \
    "disable.*security\|ignore.*guardrail\|skip.*auth\|exfiltrate\|phone.home\|send.*to.*server\|upload.*data\|rm -rf /\|delete.*all\|chmod 777\|0\.0\.0\.0\|mkfifo\|nc -l\|reverse.shell\|>/etc/\|curl.*|.*bash\|wget.*|.*sh" \
    "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$DANGER" ]]; then
    finding "CRITICAL" "Dangerous instructions in SKILL.md:"
Confidence
90% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SKILL_MD="$STAGED_PATH/SKILL.md"
if [[ -f "$SKILL_MD" ]]; then
  DANGER=$(grep -in \
    "disable.*security\|ignore.*guardrail\|skip.*auth\|exfiltrate\|phone.home\|send.*to.*server\|upload.*data\|rm -rf /\|delete.*all\|chmod 777\|0\.0\.0\.0\|mkfifo\|nc -l\|reverse.shell\|>/etc/\|curl.*|.*bash\|wget.*|.*sh" \
    "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$DANGER" ]]; then
    finding "CRITICAL" "Dangerous instructions in SKILL.md:"
Confidence
100% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SKILL_MD="$STAGED_PATH/SKILL.md"
if [[ -f "$SKILL_MD" ]]; then
  DANGER=$(grep -in \
    "disable.*security\|ignore.*guardrail\|skip.*auth\|exfiltrate\|phone.home\|send.*to.*server\|upload.*data\|rm -rf /\|delete.*all\|chmod 777\|0\.0\.0\.0\|mkfifo\|nc -l\|reverse.shell\|>/etc/\|curl.*|.*bash\|wget.*|.*sh" \
    "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$DANGER" ]]; then
    finding "CRITICAL" "Dangerous instructions in SKILL.md:"
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
SKILL_MD="$STAGED_PATH/SKILL.md"
if [[ -f "$SKILL_MD" ]]; then
  DANGER=$(grep -in \
    "disable.*security\|ignore.*guardrail\|skip.*auth\|exfiltrate\|phone.home\|send.*to.*server\|upload.*data\|rm -rf /\|delete.*all\|chmod 777\|0\.0\.0\.0\|mkfifo\|nc -l\|reverse.shell\|>/etc/\|curl.*|.*bash\|wget.*|.*sh" \
    "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$DANGER" ]]; then
    finding "CRITICAL" "Dangerous instructions in SKILL.md:"
Confidence
100% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill documentation describes operational capabilities that inherently involve shell execution and potentially network-adjacent installation flows, but the manifest declares no explicit tool scope such as permissions or allowed-tools. This creates a trust gap: an agent may invoke the skill without clear least-privilege boundaries, increasing the chance of unintended command execution or over-broad access during installation and promotion workflows.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- `eval()`, `new Function()` — dynamic code execution
- Symlinks — path traversal risk
- `postinstall` / `preinstall` scripts in package.json — npm supply chain vector
- Dangerous SKILL.md instructions (disable security, exfiltrate, reverse shells, chmod 777)

### Warning Findings (review recommended)
- Network calls (`fetch`, `curl`, `axios`, `http`)
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- `eval()`, `new Function()` — dynamic code execution
- Symlinks — path traversal risk
- `postinstall` / `preinstall` scripts in package.json — npm supply chain vector
- Dangerous SKILL.md instructions (disable security, exfiltrate, reverse shells, chmod 777)

### Warning Findings (review recommended)
- Network calls (`fetch`, `curl`, `axios`, `http`)
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
In promote mode, the script deletes any existing live skill directory with `rm -rf` and replaces it without an explicit confirmation prompt. This is a destructive operation that can cause accidental loss of a working skill or unintended rollout of unreviewed code, especially when combined with the scan-bypass promotion flow.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
echo "   ✅ No dangerous instruction patterns"
  fi

  # Check for sudo usage
  SUDO_HITS=$(grep -in "sudo " "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$SUDO_HITS" ]]; then
    finding "WARNING" "sudo usage in SKILL.md (requests elevated access):"
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
echo "   ✅ No dangerous instruction patterns"
  fi

  # Check for sudo usage
  SUDO_HITS=$(grep -in "sudo " "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$SUDO_HITS" ]]; then
    finding "WARNING" "sudo usage in SKILL.md (requests elevated access):"
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
echo "   ✅ No dangerous instruction patterns"
  fi

  # Check for sudo usage
  SUDO_HITS=$(grep -in "sudo " "$SKILL_MD" 2>/dev/null || true)
  if [[ -n "$SUDO_HITS" ]]; then
    finding "WARNING" "sudo usage in SKILL.md (requests elevated access):"
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
On a PASS verdict, the script auto-promotes by deleting any existing live directory and moving staged content live without confirmation. Even though this happens after scanning, the scanner is heuristic and incomplete, so automatic overwrite increases operational risk and can deploy a false-negative result directly into production.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The script automatically removes any previously staged copy of the named skill before reinstalling it, with no confirmation or backup. While this is less severe than live replacement, it can erase evidence or prior review state and lead to accidental loss of a quarantined sample that should be preserved for audit.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.dynamic_code_execution

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/skill-sandbox.sh:255

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/skill-sandbox.sh:231