Back to skill

Security audit

Gateway Sentinel

Security checks for vulnerabilities and agentic risk

Overview

This watchdog is mostly transparent about its purpose, but it installs a persistent background service that can automatically change the workspace and has several unsafe implementation details users should review before installing.

Install only if you are comfortable running a persistent per-user watchdog that can restart OpenClaw, run `openclaw doctor --fix`, automatically commit all unignored workspace changes once per day, and optionally perform git rollback if enabled. Before installing, set a narrow `GUARDIAN_WORKSPACE`, verify `.gitignore`, keep rollback disabled unless tested, protect `~/.openclaw/guardian.env`, rotate any exposed Telegram or Discord credentials, and consider moving logs/state out of `/tmp`.

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

Warning
Location
scripts/install-guardian.sh:59
Finding

Alert credentials are embedded in an insufficiently protected launchd plist

Content
View full analysis
/dev/null | head -1 | cut -d= -f2- | tr -d '"' || true) _tg_chat=$(grep -E '^GUARDIAN_TELEGRAM_CHAT_ID=' "$env_file" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' || true) _discord_url=$(grep -E '^GUARDIAN_DISCORD_WEBHOOK_URL=' "$env_file" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '"' || true) fi local extra_env_xml="" [[ -n "$_tg_token" ]] && extra_env_xml+=" GUARDIAN_TELEGRAM_BOT_TOKEN${_tg_token}"$'\n' [[ -n "$_tg_chat" ]] && extra_env_xml+=" GUARDIAN_TELEGRAM_CHAT_ID${_tg_chat}"$'\n' [[ -n "$_discord_url" ]] && extra_env_xml+=" GUARDIAN_DISCORD_WEBHOOK_URL${_discord_url}"$'\n' cat > "$plist_path" <EnvironmentVariables ... ${extra_env_xml} ... PLIST ``` ### Technical Analysis The installer reads reusable Telegram and Discord credentials from `~/.openclaw/guardian.env` and duplicates them directly into `~/Library/LaunchAgents/com.openclaw.guardian.plist`. The script does not establish a restrictive umask or explicitly set the generated plist to mode `0600`. Consequently, its permissions depend on the invoking user's current umask and the accessibility of parent directories. The values are also concatenated directly into XML without XML escaping. Characters such as `&`, `<`, and `>` can make the plist invalid. If an attacker can influence `guardian ...[truncated 1832 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/guardian.sh:37
Finding

Predictable files in shared /tmp allow symlink attacks and service denial of service

Content
View full analysis
/dev/null || echo "") if [[ -n "$existing_pid" ]] && kill -0 "$existing_pid" 2>/dev/null; then echo "Another guardian instance is already running (PID ${existing_pid}). Exiting." exit 1 else log_warn "Stale lockfile found (PID ${existing_pid:-unknown}). Removing." rm -f "$LOCKFILE" fi fi echo $$ > "$LOCKFILE" log_info "Lockfile acquired (PID $$)" } if [[ -f "$SNAPSHOT_DATE_FILE" ]]; then last_snapshot=$(cat "$SNAPSHOT_DATE_FILE" 2>/dev/null || echo "") fi ... echo "$today" > "$SNAPSHOT_DATE_FILE" ``` ### Technical Analysis The guardian uses fixed, globally predictable paths in `/tmp` for its lock, snapshot state, and default log. Shared temporary directories are writable by other local users. The code does not atomically create these files, reject symbolic links, verify ownership, or open them with no-follow semantics. Shell redirection and `tee -a` follow symbolic links. A malicious local user can therefore pre-create one of the expected paths as a symlink. When the guardian runs as the victim user, it may append to or overwrite the symlink target using the victim's permissions. The lock mechanism also trusts arbitrary file contents as a PID. A malicious user can place the PID of any process visible to the vic ...[truncated 1973 chars]
Remediation
View remediation
"$runtime_dir/guardian.lock" flock -n 9 || exit 1 ``` On macOS, use a compatible atomic locking mechanism when `flock` is unavailable. 4. Create state and log files with mode `0600`, reject symbolic links, and verify that existing files are regular files owned by the current UID. 5. Use atomic state updates by writing to a securely created temporary file in the private directory and then renaming it. 6. Do not infer process identity solely from a PID. If PID files remain necessary, verify the process executable and ownership. 7. Move the default log out of `/tmp`, or securely open it once using no-follow semantics and retain the file descriptor. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (50)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill description presents the package as a watchdog, but the documented behavior includes repository-wide writes via daily snapshots and optional state-altering rollback. Even though some of this is disclosed later in the document, the high-level description understates that the skill can autonomously modify git state, which can surprise operators and lead to unsafe deployment assumptions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill description presents the package as a watchdog, but the documented behavior includes repository-wide writes via daily snapshots and optional state-altering rollback. Even though some of this is disclosed later in the document, the high-level description understates that the skill can autonomously modify git state, which can surprise operators and lead to unsafe deployment assumptions.

Content

No source excerpt is available for this finding.

YARA rule 'agent_skill_destructive_autonomous_actions': Autonomous destructive filesystem, shell history, or repository actions in AI agent skills [agent_skills]

High
Category
YARA Match
Confidence
88% confidence
Finding

The skill describes autonomous repository-modifying behavior: daily git add -A && git commit and optional rollback after repeated failures. Even with opt-in for rollback and stash protection, autonomous commits and reset-based recovery can capture unintended files, create misleading history, interfere with developer workflows, or restore repository state in ways the operator did not expect.

Content

Scanner excerpt · SKILL.md (reported line 46)May include surrounding context.

md
stable commit → pop stash | After `GUARDIAN_MAX_REPAIR` failures, only if `GUARDIAN_ENABLE_ROLLBACK=true` |
| **Cooldown** | Sleep `GUARDIAN_COOLDOWN` seconds | After all levels exhausted |

> **Note:** Level 3 rollback is **off by default** and requires explicit opt-in via `GUARDIAN_ENABLE_ROLLBACK=true`. Even then, it always stashes uncommitted work before resetting — your changes are never silently discarded.

### Alerting

Guardian supports both Telegram and Discord simultaneously. If neither is configured, it runs in log-only mode.

**Alert events:**
- Guardian started / stopped
- Gateway down detected
- Each repair attempt (with level)
- Repair success / failure
- Rollback triggered
- All repairs exhausted (cooldown entered)

### Daily Snapshots

Once per calendar day, guardian runs `git add -A && git commit` in your workspace. It respects `.gitignore`, so secrets you've excluded stay excluded. Commit message format: `guardian: daily snapshot YYYY-MM-DD`.

---

## Quick Start

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

md
./scripts/guardian.sh

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 125)May include surrounding context.

md
./scripts/uninstall-guardian.sh

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
88% confidence
Finding

git reset --hard is a destructive operation that forcefully rewrites the working tree to a selected commit. Although the script attempts to stash changes first, this is still dangerous in an automated repair path because rollback target selection is based on commit-message heuristics, stash restoration can fail, and the operation can overwrite state in a production workspace without interactive confirmation.

Content

Scanner excerpt · scripts/guardian.sh (reported line 327)May include surrounding context.

sh
log_info "Rolling back to stable commit: ${stable_commit}"

  if ! git reset --hard "$stable_commit" 2>&1; then
    log_error "git reset --hard failed"
    alert "❌ Level 3 rollback git reset failed"
    if [[ "$stashed" == "true" ]]; then

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
75% 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).

Content

Scanner excerpt · SKILL.md (reported line 172)May include surrounding context.

md
log_info "Rolling back to stable commit: ${stable_commit}"

  if ! git reset --hard "$stable_commit" 2>&1; then
    log_error "git reset --hard failed"
    alert "❌ Level 3 rollback git reset failed"
    if [[ "$stashed" == "true" ]]; then
      git stash pop 2>/dev/null || log_warn "Failed to pop stash — manual recovery needed"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
75% 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).

Content

Scanner excerpt · scripts/guardian.sh (reported line 328)May include surrounding context.

sh
log_info "Rolling back to stable commit: ${stable_commit}"

  if ! git reset --hard "$stable_commit" 2>&1; then
    log_error "git reset --hard failed"
    alert "❌ Level 3 rollback git reset failed"
    if [[ "$stashed" == "true" ]]; then
      git stash pop 2>/dev/null || log_warn "Failed to pop stash — manual recovery needed"

Tool Parameter Abuse

High
Category
Tool Misuse
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).

Content

Scanner excerpt · scripts/uninstall-guardian.sh (reported line 117)May include surrounding context.

sh
echo "  ℹ️  Logs were intentionally preserved."
echo "  Log location:  \${GUARDIAN_LOG:-/tmp/openclaw-guardian.log}"
echo "  To remove logs manually:"
echo "    rm /tmp/openclaw-guardian.log /tmp/openclaw-guardian.log.1"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares shell-capable behavior but does not define any explicit tool scope or permissions boundary. For a watchdog that restarts services, runs git commands, and potentially performs rollback, omission of an allowlist increases the chance of over-broad execution in agent environments and makes its effective authority ambiguous.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
70% confidence
Finding

The skill instructs users to create persistent environment configuration under the home directory containing long-lived secrets such as Telegram bot tokens and Discord webhook URLs. Storing sensitive tokens in a reusable shell-style env file increases exposure risk through weak file permissions, backups, accidental sourcing, or later inclusion in workspace operations.

Content

Scanner excerpt · SKILL.md (reported line 70)May include surrounding context.

1. Configure environment variables

Create ~/.openclaw/guardian.env (or export in your shell profile):

bash
# Required for alerts — set at least one

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script directly sources a user-specified config file with source "$2", which executes arbitrary shell code in the guardian's process context rather than merely parsing key/value settings. Because this watchdog is designed to run persistently as a launchd/systemd service and may run with elevated privileges, a malicious or tampered config file can achieve arbitrary command execution and full compromise of the account running the service.

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

sh
if [[ -z "$GUARDIAN_TELEGRAM_BOT_TOKEN" || -z "$GUARDIAN_TELEGRAM_CHAT_ID" ]]; then
    return 0
  fi
  curl -s --max-time 10 \
    -X POST \
    "https://api.telegram.org/bot${GUARDIAN_TELEGRAM_BOT_TOKEN}/sendMessage" \
    -d "chat_id=${GUARDIAN_TELEGRAM_CHAT_ID}" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · scripts/guardian.sh (reported line 85)May include surrounding context.

sh
fi
  curl -s --max-time 10 \
    -X POST \
    "https://api.telegram.org/bot${GUARDIAN_TELEGRAM_BOT_TOKEN}/sendMessage" \
    -d "chat_id=${GUARDIAN_TELEGRAM_CHAT_ID}" \
    --data-urlencode "text=${message}" \
    -d "parse_mode=Markdown" \

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

sh
escaped=$(printf '%s' "$message" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr '\n' ' ')
    payload="{\"content\": \"${escaped}\"}"
  fi
  curl -s --max-time 10 \
    -X POST \
    -H "Content-Type: application/json" \
    -d "$payload" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The daily snapshot logic performs git add -A across the entire workspace and then commits automatically, which can silently capture all unignored files, including newly created secrets, tokens, dumps, or sensitive operational artifacts that were never meant to be versioned. In a long-running automation context, this broad write behavior is risky because it persists potentially sensitive state without explicit user review.

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/install-guardian.sh (reported line 85)May include surrounding context.

sh
[[ -n "$_cooldown" ]]        && extra_env_xml+="    <key>GUARDIAN_COOLDOWN</key><string>${_cooldown}</string>"$'\n'
  [[ -n "$_oc_port" ]]         && extra_env_xml+="    <key>OPENCLAW_PORT</key><string>${_oc_port}</string>"$'\n'

  cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

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

sh
[[ -n "$_cooldown" ]]        && extra_env_xml+="    <key>GUARDIAN_COOLDOWN</key><string>${_cooldown}</string>"$'\n'
  [[ -n "$_oc_port" ]]         && extra_env_xml+="    <key>OPENCLAW_PORT</key><string>${_oc_port}</string>"$'\n'

  cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

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/install-guardian.sh (reported line 128)May include surrounding context.

sh
[[ -n "$_cooldown" ]]        && extra_env_xml+="    <key>GUARDIAN_COOLDOWN</key><string>${_cooldown}</string>"$'\n'
  [[ -n "$_oc_port" ]]         && extra_env_xml+="    <key>OPENCLAW_PORT</key><string>${_oc_port}</string>"$'\n'

  cat > "$plist_path" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

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/install-guardian.sh (reported line 142)May include surrounding context.

sh
info "Service bootstrapped (modern launchctl)"
  else
    # Fallback for older macOS
    launchctl load -w "$plist_path" 2>/dev/null || true
    info "Service loaded (legacy launchctl)"
  fi

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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/install-guardian.sh (reported line 147)May include surrounding context.

sh
fi

  info "Service loaded and enabled"
  info "To configure alerts, create ~/.openclaw/guardian.env with your GUARDIAN_TELEGRAM_* or GUARDIAN_DISCORD_* vars."
  echo ""
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  echo "  OpenClaw Guardian installed (macOS launchd)"

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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/install-guardian.sh (reported line 167)May include surrounding context.

sh
local unit_dir="$HOME/.config/systemd/user"
  local unit_path="${unit_dir}/openclaw-guardian.service"

  mkdir -p "$unit_dir"

  cat > "$unit_path" <<UNIT
[Unit]

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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/install-guardian.sh (reported line 193)May include surrounding context.

sh
info "Unit file written to: ${unit_path}"

  systemctl --user daemon-reload
  systemctl --user enable --now openclaw-guardian.service

  info "Service enabled and started"
  info "To configure alerts, create ~/.openclaw/guardian.env with your GUARDIAN_TELEGRAM_* or GUARDIAN_DISCORD_* vars."

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/install-guardian.sh (reported line 4)May include surrounding context.

sh
#!/usr/bin/env bash
# uninstall-guardian.sh — Remove OpenClaw Guardian service
#
# Stops the running service, removes the plist or systemd unit, and cleans
# the lockfile. Logs are intentionally preserved.
#
# Usage: ./uninstall-guardian.sh

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/install-guardian.sh (reported line 47)May include surrounding context.

sh
#!/usr/bin/env bash
# uninstall-guardian.sh — Remove OpenClaw Guardian service
#
# Stops the running service, removes the plist or systemd unit, and cleans
# the lockfile. Logs are intentionally preserved.
#
# Usage: ./uninstall-guardian.sh

Static analysis

No suspicious patterns detected.