Back to skill

Security audit

OpenClaw Watchdog Pro

Security checks for vulnerabilities and agentic risk

Overview

This watchdog mostly matches its stated purpose, but it installs long-running privileged services and can make automatic repair or rollback changes without enough user control.

Install only if you intentionally want a persistent OpenClaw watchdog. Review the installer first, avoid running it with administrator privileges unless absolutely necessary, consider disabling automatic repair/rollback, and prefer a least-privileged user service with a clear uninstall procedure.

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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/install.cjs:66
Finding

Watchdog Persistence Runs with Unnecessary Root or SYSTEM Privileges

Content
View full analysis
{}); execSync( `schtasks /create /tn "${taskName}" /tr "node ${scriptPath} monitor" /sc onstart /ru SYSTEM /rl highest /f`, { encoding: 'utf8' } ); return true; } catch (e) { return false; } } ``` ### Technical Analysis The installer creates a reboot-persistent systemd service on Linux and a boot-triggered scheduled task on Windows. The Linux service explicitly uses `User=root`, while the Windows task uses `/ru SYSTE ...[truncated 2162 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/watchdog.cjs:568
Finding

Shell Command Injection in the OpenClaw Command Wrapper

Content
View full analysis
cmdStr.includes(cmd))) { log(`Detected configuration-modifying command: ${cmdStr}`); backupConfig(); } try { const result = execSync(`openclaw ${args.join(' ')}`, { encoding: 'utf8', stdio: 'inherit' }); process.exit(0); } catch (e) { process.exit(e.status || 1); } } ``` The original log message differs in language, but the vulnerable command construction is unchanged: ```js execSync(`openclaw ${args.join(' ')}`, { encoding: 'utf8', stdio: 'inherit' }); ``` ### Technical Analysis Arguments supplied to the `wrap` command are joined with spaces and interpolated directly into a string passed to `execSync`. By default, `execSync` executes string commands through a shell. Consequently, shell metacharacters are interpreted instead of being passed literally to the `openclaw` executable. Potentially dangerous input includes command separators, command substitution, redirection, pipelines, and environment expansion. The implementation does not quote or validate individual arguments. The wrapper is exposed through the installer-created `oc` shell alias, making this an intended user-facing execution path. The issue is especially severe if the wrapper is invoked from an elevated shell or privileged automation context. ### Attack Path 1. A local user, script, plugin, or automation system invokes: `watchdog.cjs wrap` with an argument containing shell syntax. 2. `args.join(' ' ...[truncated 1062 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/install.cjs:150
Finding

Installer Interpolates Filesystem Paths into Shell Commands

Content
View full analysis
{}); execSync(`launchctl load ${plistPath}`, { encoding: 'utf8' }); ``` ```js execSync(`crontab ${tmpFile}`, { encoding: 'utf8' }); ``` ```js execSync(`schtasks /delete /tn "${taskName}" /f`, { encoding: 'utf8', stdio: 'ignore' }).catch(() => {}); execSync( `schtasks /create /tn "${taskName}" /tr "node ${scriptPath} monitor" /sc onstart /ru SYSTEM /rl highest /f`, { encoding: 'utf8' } ); ``` ### Technical Analysis The installer interpolates `plistPath`, `tmpFile`, and `scriptPath` into shell command strings. These values are derived from the user's home directory, temporary directory, or the package installation path. They are not safely passed as distinct process arguments. Paths containing whitespace can cause argument splitting and installation failure. Paths containing shell metacharacters can alter the command interpreted by the shell. This is particularly dangerous because the installer may be run with administrator privileges in order to create system services or SYSTEM tasks. The Windows task command also embeds a script path into nested command-line quoting. A path containing spaces or special characters can change how `schtasks` stores or executes the task action. In addition, `.catch()` is invoked on the synchronous return value of `execSync`. `execSync` does not return a Promise, so a successful command can be followed by a `TypeError`, causing misleading installation behavior. ### Attack Path 1. The Skill is installed under a path containing spaces or shell-significant characters, or the ...[truncated 959 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/watchdog.cjs:286
Finding

Asynchronous Gateway Verification Is Treated as an Immediate Success

Content
View full analysis
{ const config = loadConfig(); const timeout = config.gatewayStartTimeoutMs; const startTime = Date.now(); const check = () => { if (checkGateway()) { resolve(true); } else if (Date.now() - startTime > timeout) { log('Gateway startup timed out', 'error'); resolve(false); } else { setTimeout(check, 1000); } }; setTimeout(check, 2000); }); } ``` The security-relevant condition in the original source is: ```js if (checkGateway()) { resolve(true); } ``` ### Technical Analysis `checkGateway()` returns a Promise rather than a Boolean. Promise objects are truthy in JavaScript, regardless of the Boolean value with which they eventually resolve. Therefore, the first health-check attempt always enters the success branch. After a recovery attempt, the watchdog can record the gateway as successfully restarted without waiting for the TCP and WebSocket probe. It then resets failure counters and recovery counters. This undermines the reliability of the automatic recovery and `doctor --fix` escalation logic. This is principally an availability and integrity issue. It does not by itself provide arbitrary code execution, but it can hide a failed gateway state and prevent intended repairs. ### Attack Path 1. The gateway fails two consecutive watchdog checks. 2. The watchdog restores the latest backup and issues `openclaw gateway start`. 3. The start command returns successfully even though the gateway does not become healthy. 4. `verifyGatewayRunning()` calls `checkGateway()`. 5. The ...[truncated 735 chars]
Remediation
View remediation
{ const config = loadConfig(); const timeout = config.gatewayStartTimeoutMs; const startTime = Date.now(); const check = async () => { const healthy = await checkGateway(); if (healthy) { resolve(true); } else if (Date.now() - startTime > timeout) { log('Gateway startup timed out', 'error'); resolve(false); } else { setTimeout(check, 1000); } }; setTimeout(check, 2000); }); } ``` Additional hardening: 1. Validate `gatewayStartTimeoutMs` as a finite positive integer. 2. Use one configurable gateway host and port consistently across all probe functions. 3. Ensure every probe settles exactly once and always destroys its socket. 4. Add tests where the start command succeeds but the gateway never opens its port. 5. Add tests for delayed startup, invalid WebSocket responses, connection refusal, and timeout behavior. 6. Do not reset recovery counters until an awaited health check has conclusively succeeded. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (48)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation instructs first-time users to run an installation script that will configure persistent execution and start a service, but the warning is not sufficiently explicit about the scope of system changes. Automatically modifying startup mechanisms and launching background processes is sensitive behavior that can materially alter the host environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The automatic recovery behavior restores backups and may roll back the active configuration, but the user-facing text does not clearly warn that recent changes can be overwritten. In a configuration-management context, silent rollback can cause data loss, service disruption, or reintroduction of insecure or stale settings.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

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

schtasks /query /tn "OpenClaw Watchdog"

删除并重新创建

schtasks /delete /tn "OpenClaw Watchdog" /f

text

#### cron (备用方案)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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/install.cjs (reported line 210)May include surrounding context.

js
schtasks /query /tn "OpenClaw Watchdog"

# 删除并重新创建
schtasks /delete /tn "OpenClaw Watchdog" /f
```

#### cron (备用方案)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/install.cjs (reported line 172)May include surrounding context.

js
{
        log(`✗ launchd 配置失败:${e.message}`, 'red');
        return false;
    }
}

function setupCron() {
    log('检测到 cron,创建定时任务...', 'blue');
    
    const cronJob = `* * * * * node ${WATCHDOG_SCRIPT} check || node ${WATCHDOG_SCRIPT} recover`;
    
    try {
        // 获取当前 crontab
        let current = '';
        try {
            current = execSync('crontab -l', { encoding: 'utf8' });
        } catch (e) {
            // 没有 crontab 是正常的
        }
        
        // 检查是否已存在
        if (current.includes('openclaw-watchdog') || current.includes(WATCHDOG_SCRIPT)) {
            log('⚠ cron 任务已存在,跳过', 'yellow');
            return true;
        }
        
        // 添加新任务
        const newCrontab = current + '\n# OpenClaw Watchdog\n' + cronJob + '\n';
        
        // 写入临时文件
        const tmpFile = path.join(os.tmpdir(), 'watchdog-cron-' + process.pid);
        fs.writeFileSy

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script can automatically execute openclaw doctor --fix --non-interactive after repeated failures, giving it autonomous repair authority that can change configuration or system state without user approval at execution time. In a watchdog context, this expands privilege and blast radius from monitoring/restart into unsupervised remediation, which can cause unintended changes or be abused if the underlying openclaw command path or environment is compromised.

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/watchdog.cjs (reported line 750)May include surrounding context.

js
ystemd 服务
        if (fs.existsSync('/etc/systemd/system/openclaw-watchdog.service')) {
            try {
                const status = execSync('systemctl is-active openclaw-watchdog', { encoding: 'utf8' });
                return status.trim() === 'active';
            } catch (e) {
                return false;
            }
        }
        // 检查 cron
        try {
            const crontab = execSync('crontab -l', { encoding: 'utf8' });
            if (crontab.includes('watchdog.cjs')) {
                return true;
            }
        } catch (e) {
            // 无 crontab
        }
    }
    
    if (platform === 'darwin') {
        const plistPath = path.join(HOME_DIR, 'Library', 'LaunchAgents', 'com.openclaw.watchdog.plist');
        return fs.existsSync(plistPath);
    }
    
    if (platform === 'win32') {
        try {
            execSync('schtasks /query /tn "OpenClaw Watchdog"', { encoding: 'utf8', stdio: 'ignore' });
            return true;
        } catc

Chaining Abuse

High
Category
Tool Misuse
Confidence
84% confidence
Finding

The cleanup pipeline uses 'ls | tail | xargs rm', which is unsafe for filenames containing spaces, newlines, or leading dashes and can mis-handle attacker-created backup filenames. In a privileged context under /root, this can cause unintended file deletion within the backup workflow and makes destructive behavior depend on shell parsing rather than exact path handling.

Content

Scanner excerpt · scripts/watchdog.sh (reported line 32)May include surrounding context.

sh
log "备份完成:$backup_file"
        
        # 清理旧备份,保留最近 MAX_BACKUPS 个
        ls -t "$BACKUP_DIR"/openclaw.*.json 2>/dev/null | tail -n +$((MAX_BACKUPS + 1)) | xargs -r rm
        log "旧备份已清理,保留最近 $MAX_BACKUPS 个"
    fi
}

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises installation, monitoring, persistence setup, log access, and command execution, but does not declare an explicit tool scope such as permissions or allowed-tools. This creates a mismatch between documented behavior and declared capability boundaries, increasing the risk that an agent may invoke shell, environment, or network actions without clear user-visible restriction.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger words include broad operational terms like 配置备份, 自动恢复, 看门狗, and watchdog without clear activation boundaries or confirmation requirements. In an agent setting, broad triggers can cause unintended invocation of a skill that installs persistence, monitors services, or modifies configuration.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

L003 的自然语言描述完全使用中文,且文档整体未说明这是面向特定中文用户群或区域的限定技能,也未提供语言可选项。若组织要求避免未经用户选择即强制特定语言/locale,这构成语言策略层面的潜在违规。

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill describes reading and analyzing gateway logs for error patterns, but does not clearly warn users that log content will be accessed and processed. Logs may contain tokens, identifiers, message metadata, endpoints, or other sensitive operational information, so undisclosed inspection raises privacy and security concerns.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The skill documents use of launchd LaunchAgents for persistent execution on macOS. Persistence is expected for a watchdog, but in an agent skill it remains security-sensitive because it causes code to re-run automatically across sessions and can outlive the initiating user interaction.

Content

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

bash
launchctl list | grep openclaw
launchctl unload ~/Library/LaunchAgents/com.openclaw.watchdog.plist
launchctl load ~/Library/LaunchAgents/com.openclaw.watchdog.plist

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

This duplicate persistence indicator still corresponds to the same security-relevant behavior: a macOS plist-based autorun configuration. In context, persistence is not inherently malicious, but it is a true security-sensitive capability that should be tightly disclosed and user-approved.

Content

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

bash
launchctl list | grep openclaw
launchctl unload ~/Library/LaunchAgents/com.openclaw.watchdog.plist
launchctl load ~/Library/LaunchAgents/com.openclaw.watchdog.plist

Windows

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

This duplicate persistence indicator still corresponds to the same security-relevant behavior: a macOS plist-based autorun configuration. In context, persistence is not inherently malicious, but it is a true security-sensitive capability that should be tightly disclosed and user-approved.

Content

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

bash
launchctl list | grep openclaw
launchctl unload ~/Library/LaunchAgents/com.openclaw.watchdog.plist
launchctl load ~/Library/LaunchAgents/com.openclaw.watchdog.plist

Windows

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest describes backup/monitoring/recovery, but the installer sets up persistent services/tasks across systemd, launchd, cron, and Windows Task Scheduler, including root/SYSTEM execution paths. While persistence is partly consistent with a watchdog, doing so with elevated privileges and broad system integration materially increases risk if the watchdog script is compromised or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The installer writes a systemd service under /etc/systemd/system, enables autostart, and restarts the service without any up-front warning or consent flow. Unprompted persistent system modification is risky because users may not understand they are granting long-lived execution, especially when combined with elevated service context.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

systemctl enable configures the watchdog to start automatically on boot, which is a classic persistence mechanism. This aligns with watchdog behavior, but persistence should still be treated as security-sensitive because it causes repeated unattended execution.

Content

Scanner excerpt · scripts/install.cjs (reported line 95)May include surrounding context.

js
execSync('systemctl daemon-reload', { encoding: 'utf8' });
        log('✓ systemd 配置已重载', 'green');
        
        execSync('systemctl enable openclaw-watchdog', { encoding: 'utf8' });
        log('✓ 服务已启用(开机自启)', 'green');
        
        execSync('systemctl restart openclaw-watchdog', { encoding: 'utf8' });

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.cjs (reported line 111)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 112)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 115)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 116)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 119)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 120)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

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.cjs (reported line 121)May include surrounding context.

js
function setupLaunchd() {
    log('检测到 macOS,创建 launchd 配置...', 'blue');
    
    const plistDir = path.join(HOME, 'Library', 'LaunchAgents');
    const plistPath = path.join(plistDir, 'com.openclaw.watchdog.plist');
    
    // 确保目录存在

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/install.cjs:31

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/watchdog.cjs:133