Back to skill

Security audit

OpenClaw Doctor

Security checks for vulnerabilities and agentic risk

Overview

This OpenClaw diagnostic skill is mostly coherent, but its repair mode can change services and run a separate workspace script without enough guardrails.

Install only if you want an agent to run local OpenClaw health checks. Treat the default diagnostic as read-only, but do not use --fix unless you are comfortable with service restarts, LaunchAgent loading, config permission changes, and execution of a workspace log-rotation script that should be inspected first.

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

Warning
Location
scripts/diagnose.sh:151
Finding

Execution of an Untrusted Workspace Log-Rotation Script

Content
View full analysis
/dev/null 2>&1 && fixed "Logs rotated" fi ``` ### Technical Analysis When invoked with `--fix`, the diagnostic executes `~/.openclaw/workspace/scripts/log_rotate.sh` if the OpenClaw log directory exceeds 500 MB. This script is outside the audited Skill package and may reside in a user-modifiable workspace. Before execution, the code only confirms that the path is a regular file. It does not validate: - The file's owner or group - Whether its permissions permit modification by untrusted users - Its canonical path or possible symbolic-link resolution - Its provenance or relationship to this Skill - Its integrity through a pinned cryptographic hash - Whether the file changed between validation and execution Consequently, the diagnostic crosses a local trust boundary by treating a mutable workspace file as executable trusted code. Quoting the path prevents argument splitting but does not mitigate malicious contents within the script. ### Attack Path 1. An attacker, compromised process, malicious extension, or other actor with write access to `~/.openclaw/workspace/scripts/` creates or replaces `log_rotate.sh`. 2. The attacker inserts arbitrary shell commands into that file. 3. The OpenClaw log directory reaches the script's failure threshold of at least 500 MB. 4. A user or agent invokes: ```bash bash scripts/diagnose.sh --fix ``` 5. The diagnostic launches the attacker-controlled file with `bash`. 6. The injected commands execute under the identity and environment of the account running the diagnostic. This path requires local write access to the workspace and explicit use of `--fix`; it is not triggered during the documented read-on ...[truncated 783 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill advertises automatic fixes including restarting services, changing file permissions, rotating logs, clearing session data, and restarting channels, but the description does not prominently require user approval before those write operations. Because the skill is framed as routine diagnostics and health checks, users may trigger it expecting read-only inspection while the agent performs disruptive or destructive changes.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill clearly instructs the agent to execute a shell script (scripts/diagnose.sh) yet declares no explicit tool scope or permission boundaries. That creates an authorization ambiguity where a troubleshooting request can invoke command execution without the skill manifest clearly constraining or disclosing that capability.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation phrasing is broad enough to match ordinary troubleshooting requests such as 'system feels slow' or 'diagnose my setup,' which can cause this skill to be selected unexpectedly. In this context, accidental activation is more dangerous because the skill is tied to shell execution and repair behavior, increasing the chance of unintended diagnostics or system changes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The --fix path performs immediate state-changing actions, including restarting the gateway service, without any interactive confirmation, dry-run, or additional guardrail. In a diagnostic skill, this can unexpectedly disrupt running workloads or change host state when invoked by an agent or user who only intended inspection.

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 · scripts/diagnose.sh (reported line 64)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 65)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 76)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 77)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 80)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 81)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 82)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 83)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 84)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 64)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 66)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

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 · scripts/diagnose.sh (reported line 87)May include surrounding context.

sh
# Service configuration
if [ "$OS" = "Darwin" ]; then
  PLIST="$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist"
  if [ -f "$PLIST" ]; then
    pass "LaunchAgent plist exists"
    if launchctl list 2>/dev/null | grep -q "ai.openclaw.gateway"; then

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

In --fix mode, the script will load a user LaunchAgent automatically, which re-enables persistent execution at login without a separate confirmation prompt. In the context of an agent skill, automatic persistence-related actions are more sensitive because they can change long-lived execution behavior on the host beyond a one-time diagnostic run.

Content

Scanner excerpt · scripts/diagnose.sh (reported line 73)May include surrounding context.

sh
else
      fail "LaunchAgent not loaded"
      if $FIX; then
        launchctl load "$PLIST" 2>/dev/null && fixed "LaunchAgent loaded"
      fi
    fi
    grep -q "<key>KeepAlive</key>" "$PLIST" 2>/dev/null && pass "KeepAlive enabled" || warn "KeepAlive not configured"

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

In --fix mode, the script will load a user LaunchAgent automatically, which re-enables persistent execution at login without a separate confirmation prompt. In the context of an agent skill, automatic persistence-related actions are more sensitive because they can change long-lived execution behavior on the host beyond a one-time diagnostic run.

Content

Scanner excerpt · scripts/diagnose.sh (reported line 73)May include surrounding context.

sh
else
      fail "LaunchAgent not loaded"
      if $FIX; then
        launchctl load "$PLIST" 2>/dev/null && fixed "LaunchAgent loaded"
      fi
    fi
    grep -q "<key>KeepAlive</key>" "$PLIST" 2>/dev/null && pass "KeepAlive enabled" || warn "KeepAlive not configured"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/diagnose.sh (reported line 154)May include surrounding context.

sh
section "Power & Resilience"
  
  AUTO_RESTART=$(pmset -g 2>/dev/null | awk '/autorestart/ {print $2}')
  [ "$AUTO_RESTART" = "1" ] && pass "Auto-restart after power loss" || warn "Auto-restart disabled (sudo pmset -a autorestart 1)"
  
  SLEEP_VAL=$(pmset -g 2>/dev/null | awk '/^ sleep / {print $2}')
  [ "$SLEEP_VAL" = "0" ] && pass "System never sleeps" || warn "System may sleep (sleep=$SLEEP_VAL, fix: sudo pmset -a sleep 0)"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/diagnose.sh (reported line 157)May include surrounding context.

sh
section "Power & Resilience"
  
  AUTO_RESTART=$(pmset -g 2>/dev/null | awk '/autorestart/ {print $2}')
  [ "$AUTO_RESTART" = "1" ] && pass "Auto-restart after power loss" || warn "Auto-restart disabled (sudo pmset -a autorestart 1)"
  
  SLEEP_VAL=$(pmset -g 2>/dev/null | awk '/^ sleep / {print $2}')
  [ "$SLEEP_VAL" = "0" ] && pass "System never sleeps" || warn "System may sleep (sleep=$SLEEP_VAL, fix: sudo pmset -a sleep 0)"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/diagnose.sh (reported line 193)May include surrounding context.

sh
else
    warn "Config permissions $PERM (should be 600)"
    if $FIX; then
      chmod 600 "$OC_HOME/openclaw.json" 2>/dev/null && fixed "Config permissions set to 600"
    fi
  fi
fi