Back to skill

Security audit

Watchdog - Open claw - Mac

Security checks for vulnerabilities and agentic risk

Overview

This watchdog is mostly purpose-aligned, but it has risky automatic side effects and insecure command construction that users should review before installing.

Install only if you are comfortable with a watchdog that can run indefinitely, rewrite ~/.pi/config.json, restart or force-kill llama-server processes, kickstart an OpenClaw service, and send operational alerts to Telegram when credentials are present. Review and harden the script first, especially the Python/AppleScript interpolation and process matching, and run it as an unprivileged user with DRY_RUN or notifications disabled until you understand the effects.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
rock-solid-watchdog.sh:285
Finding

Arbitrary Python Code Execution Through Environment-Variable Interpolation

Content
View full analysis
/dev/null || { ``` ### Technical Analysis The script interpolates shell-controlled values directly into the source text supplied to `python3 -c`. In particular, `LLAMA_HOST`, `LLAMA_PORT`, `PI_CONFIG_FILE`, and the temporary filename are inserted into Python string literals or expressions without Python-safe encoding. An attacker who can influence the watchdog's environment can provide a value containing quote characters and additional Python statements. When `ensure_pi_port_alignment` detects a missing or misaligned Pi configuration, the generated source is parsed and executed by Python. Shell quoting around the overall `python3 -c` argument does not protect the resulting Python program from Python syntax injection. `LLAMA_PORT` is especially dangerous because it is inserted as an unquoted Python expression: ```python cfg['llm']['port'] = $llama_port ``` The values are also used earlier in generated JSON, so strict type and content validation is necessary independently of the injection fix. ### Attack Path 1. The attacker obtains a way to control environment variables used to launch the watchdog, such as a service configuration, wrapper script, shell profile, or invocation command. 2. The attacker assigns malicious Python syntax to `LLAMA_HOST`, `LLAMA_PORT`, or another interpolate ...[truncated 950 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
rock-solid-watchdog.sh:75
Finding

AppleScript Injection Through macOS Notification Content

Content
View full analysis
/dev/null || true } ``` An environment-controlled invocation of this function occurs during startup at line 418: ```bash bark "Watchdog started" "llama.cpp on $LLAMA_PORT | log: $LOG_FILE" ``` ### Technical Analysis The notification title and message are concatenated directly into AppleScript source. Double quotes in `msg` or `title` are not escaped for the AppleScript language. Consequently, a value can terminate the intended string literal and introduce additional AppleScript statements. The startup notification includes environment-derived `LLAMA_PORT` and `LOG_FILE` values. Other calls also pass runtime values into the same sink. Shell quoting only determines how Bash constructs the single `osascript` argument; it does not prevent the completed argument from containing executable AppleScript syntax. The command suppresses all errors and continues, making attempted exploitation or malformed notification input difficult to detect in normal operation. ### Attack Path 1. The attacker gains control over an environment value used in a notification, such as `LLAMA_PORT` or `LOG_FILE`. 2. The attacker inserts AppleScript string termination characters and additional AppleScript commands into that value. 3. The watchdog starts with `NOTIFY_MACOS=1`, which is the default. 4. Startup calls `bark`, which calls `notify_macos`. 5. `notify_macos` embeds the attacker-controlled text into the source supplied to `osascript -e`. 6. macOS executes the injected AppleScript under the watchdog user's account. ### Impact Assessment Successful exploitation permits arbitrary AppleScript execution as the watchdog user. I ...[truncated 538 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
rock-solid-watchdog.sh:179
Finding

Overbroad Process Matching Terminates Unrelated llama-server Instances

Content
View full analysis
/dev/null || true) if [[ -n "$pids" ]]; then info "Killing existing llama-server PIDs: $pids" echo "$pids" | xargs kill -TERM 2>/dev/null || true sleep 2 # Force kill if still running pids=$(pgrep -f "llama-server" 2>/dev/null || true) if [[ -n "$pids" ]]; then echo "$pids" | xargs kill -KILL 2>/dev/null || true sleep 1 fi fi ``` ### Technical Analysis `pgrep -f "llama-server"` searches every accessible process's full command line for the text `llama-server`. It does not verify that a match is the instance configured by `LLAMA_SERVER`, bound to `LLAMA_PORT`, launched by this watchdog, or associated with a watchdog-maintained PID. When a restart occurs, every matching process is first sent `SIGTERM`. After two seconds, the script repeats the same broad search and sends `SIGKILL` to every remaining match. This may terminate independent inference servers, wrapper processes whose command lines contain the string, and unrelated jobs owned by the same account. The health check uses the same broad matching assumption at lines 139-144, so an unrelated llama-server can also make the process-presence stage appear healthy even when the intended instance is absent. ### Attack Path 1. Multiple llama-server instances or another process containing `llama-server` in its command line run under the watchdog user's account. 2. The monitored endpoint fails enough consecutive checks to trigger `restart_llama`. 3. The restart function executes `pgrep -f "llama-server"` without checking the configured executable, port, ownership relationship, or PID file. 4. The script sends `SIGTERM` to all returned PIDs. 5. Any matching processes still present after two seconds re ...[truncated 684 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
rock-solid-watchdog.sh:260
Finding

Undocumented Configuration Mutation, External Notification, and Service-Control Side Effects

Content
View full analysis
"$PI_CONFIG_FILE" <<-EOF { "llm": { "host": "$LLAMA_HOST", "port": $llama_port, "provider": "llama.cpp" }, "sync_from_watchdog": true, "updated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" } EOF bark "Pi config created" "llama.cpp endpoint set to ${LLAMA_HOST}:${llama_port}" return 0 fi ``` After producing an updated temporary file, it replaces the Pi configuration: ```bash mv "$tmpfile" "$PI_CONFIG_FILE" info "Pi config updated successfully" bark "Pi port aligned" "→ ${LLAMA_HOST}:${llama_port}" ``` Telegram notifications are enabled by default and use configured credentials at lines 81-91: ```bash notify_telegram() { [[ "$NOTIFY_TELEGRAM" != "1" ]] && return 0 local title="$1" msg="$2" local bot_token="${TELEGRAM_BOT_TOKEN:-}" local chat_id="${TELEGRAM_CHAT_ID:-}" [[ -z "$bot_token" || -z "$chat_id" ]] && return 0 curl -s -X POST "https://api.telegram.org/bot${bot_token}/sendMessage" \ -d "chat_id=${chat_id}" \ -d "text=🔔 Watchdog: ${title} — ${msg}" \ -d "disable_notification=true" >/dev/null 2>&1 || true } ``` Gateway failure can trigger an existing launch service at lines 432-437: ```bash if (( CONSECUTIVE_FAILS % MAX_CONSECUTIVE_FAILS == 0 )); then bark "Gateway DOWN" "attempting launchctl kickstart" launchctl kickstart "gui/$(id -u)/homebrew.mxcl.openclaw" 2>/dev/null || \ launchctl kickstart "homebrew.mxcl.openclaw" 2>/dev/null || \ warn "launchctl kickstart failed" f ...[truncated 2655 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file advertises that the watchdog will automatically restart services and run custom scripts on failure or escalation, which can affect system state and execute user-defined actions. The description does not include any caution about these behaviors, their side effects, or the need to review hook scripts before use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script transmits operational event details to Telegram, an external third-party service, without any built-in disclosure, consent prompt, or clear minimization of what may be sent. While the current messages appear limited to watchdog titles and status text, those strings can include local ports, file paths, service names, and failure details, creating an avoidable data exposure channel.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The hardcoded use of the Telegram API confirms deliberate outbound communication to an external service. In a watchdog context this is not inherently malicious, but it still expands data exposure and dependency on a third-party platform for operational telemetry.

Content

Scanner excerpt · rock-solid-watchdog.sh (reported line 87)May include surrounding context.

sh
local bot_token="${TELEGRAM_BOT_TOKEN:-}"
  local chat_id="${TELEGRAM_CHAT_ID:-}"
  [[ -z "$bot_token" || -z "$chat_id" ]] && return 0
  curl -s -X POST "https://api.telegram.org/bot${bot_token}/sendMessage" \
    -d "chat_id=${chat_id}" \
    -d "text=🔔 Watchdog: ${title} — ${msg}" \
    -d "disable_notification=true" >/dev/null 2>&1 || true

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The hardcoded use of the Telegram API confirms deliberate outbound communication to an external service. In a watchdog context this is not inherently malicious, but it still expands data exposure and dependency on a third-party platform for operational telemetry.

Content

Scanner excerpt · rock-solid-watchdog.sh (reported line 87)May include surrounding context.

sh
local bot_token="${TELEGRAM_BOT_TOKEN:-}"
  local chat_id="${TELEGRAM_CHAT_ID:-}"
  [[ -z "$bot_token" || -z "$chat_id" ]] && return 0
  curl -s -X POST "https://api.telegram.org/bot${bot_token}/sendMessage" \
    -d "chat_id=${chat_id}" \
    -d "text=🔔 Watchdog: ${title} — ${msg}" \
    -d "disable_notification=true" >/dev/null 2>&1 || true

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The watchdog automatically kills existing llama-server processes with TERM/KILL and launches replacement processes in the background. While the function name suggests restart behavior, there is no explicit safety warning that this script performs destructive process control and force-kill actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 · rock-solid-watchdog.sh (reported line 193)May include surrounding context.

sh
log "DRY_RUN: would run $LLAMA_START_SCRIPT"
      return 0
    fi
    nohup bash "$LLAMA_START_SCRIPT" >> "$LOG_FILE" 2>&1 &
    local start_pid=$!
    info "Start script launched (pid=$start_pid)"
  elif [[ -x "$LLAMA_SERVER" ]]; then

Session Persistence

Medium
Category
Rogue Agent
Confidence
65% 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 · rock-solid-watchdog.sh (reported line 206)May include surrounding context.

sh
log "DRY_RUN: would run $LLAMA_START_SCRIPT"
      return 0
    fi
    nohup bash "$LLAMA_START_SCRIPT" >> "$LOG_FILE" 2>&1 &
    local start_pid=$!
    info "Start script launched (pid=$start_pid)"
  elif [[ -x "$LLAMA_SERVER" ]]; then

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This function creates and overwrites fields in the Pi config file, affecting local application configuration. The script logs these actions internally, but it does not clearly warn users up front that running the watchdog will continuously modify configuration state.

Content

No source excerpt is available for this finding.