Back to skill

Security audit

Failure Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent cron failure monitor, but it can run unattended and automatically edit cron jobs or change file permissions using unsafe inputs.

Review carefully before installing. Use only under a least-privileged account, restrict who can edit OpenClaw cron metadata, and prefer a revised version that validates job IDs and script paths, uses argument-array process execution instead of shell strings, and requires explicit confirmation for chmod or other high-impact repairs.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/monitor.cjs:220
Finding

Shell Command Injection Through Untrusted Cron Job Metadata

Content
View full analysis

Vulnerability Details

File Location: scripts/monitor.cjs, lines 220–231
Vulnerability Type: OS command injection
Risk Level: High

Vulnerable Code

js
const cmd = `openclaw cron edit ${job.id} --timeout-seconds ${params.to}`;
execSync(cmd, { encoding: 'utf8' });
js
const cmd = `openclaw cron edit ${job.id} --channel ${params.channel} --to "${job.delivery?.to || 'last'}"`;
execSync(cmd, { encoding: 'utf8' });

Technical Analysis

The monitor reads job.id and job.delivery.to from the external OpenClaw jobs.json file and directly interpolates these values into commands passed to execSync(). Node.js executes string commands through a shell, so shell metacharacters contained in these fields can alter the intended command.

Placing job.delivery.to inside double quotes does not make it safe. An attacker can potentially use embedded quotes, command substitution, or other shell syntax to escape the intended argument. job.id is not quoted at all.

Exploitation requires the attacker to create or modify a cron-job record, or otherwise influence the metadata consumed by the monitor. The affected record must report a failure matching an automatic-repair rule so that one of the vulnerable methods is invoked.

Attack Path

  1. An attacker gains the ability to create or modify an entry in the OpenClaw cron jobs.json file.
  2. The attacker inserts shell syntax into job.id or job.delivery.to.
  3. The attacker configures the job state with an error message such as job execution timed out or Channel is required.
  4. The monitor identifies the job as failed and selects the corresponding automatic repair.
  5. The malicious field is interpolated into a command string.
  6. execSync() invokes the shell, which interprets the injected syntax and executes the attacker's command.

Impact Assessment

Successful exploitation permits arbitrary command execution with the operating- ...[truncated 421 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace shell-based execSync() calls with execFileSync() or spawnSync() and pass each argument separately:

    js
    const { execFileSync } = require('child_process');
    
    execFileSync('openclaw', [
      'cron',
      'edit',
      String(job.id),
      '--timeout-seconds',
      String(params.to)
    ], {
      encoding: 'utf8',
      shell: false
    });
    
  • Apply the same argument-array approach to delivery configuration:

    js
    execFileSync('openclaw', [
      'cron',
      'edit',
      String(job.id),
      '--channel',
      String(params.channel),
      '--to',
      String(job.delivery?.to || 'last')
    ], {
      encoding: 'utf8',
      shell: false
    });
    
  • Validate job.id against the exact identifier format accepted by OpenClaw. Reject whitespace, control characters, shell metacharacters, and malformed identifiers.

  • Validate channels and delivery destinations against explicit allowlists.

  • Treat the cron jobs file as security-sensitive input and restrict its ownership and write permissions.

  • Run the monitor under a dedicated, least-privileged operating-system account.

  • Add tests using malicious values containing semicolons, quotes, command substitutions, newlines, and option-like prefixes.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/monitor.cjs:234
Finding

Unrestricted Automatic Permission Changes Based on Job Message Content

Content
View full analysis

Vulnerability Details

File Location: scripts/monitor.cjs, lines 234–249
Vulnerability Type: Unsafe file permission modification
Risk Level: Medium

Vulnerable Code

js
const message = job.payload?.message || '';
const scriptMatch = message.match(/(\/[\w\/\-\.]+\.(?:sh|py|js|cjs|mjs))/);

if (scriptMatch) {
  const scriptPath = scriptMatch[1];
  const cmd = `chmod +x ${scriptPath}`;
  execSync(cmd, { encoding: 'utf8' });
}

Technical Analysis

When a failed job reports Permission denied, the monitor extracts the first matching absolute script path from arbitrary job.payload.message content and automatically grants that file executable permission.

The code does not verify that:

  • The path belongs to the failed job.
  • The file is inside an approved scripts directory.
  • The file is a regular file rather than a symbolic link or another filesystem object.
  • The file is owned by the expected user.
  • The resolved canonical path remains within an authorized location.
  • The permission change was approved by an operator.

The path regular expression excludes common shell metacharacters, so direct command injection through this particular value was not confirmed. However, it still accepts absolute paths across the filesystem and permits an attacker controlling job content to select which accessible file receives executable permission.

Attack Path

  1. An attacker creates or modifies a cron-job record or otherwise controls its payload message.
  2. The attacker places an absolute path ending in .sh, .py, .js, .cjs, or .mjs in the message.
  3. The job is marked failed with a Permission denied error.
  4. The monitor classifies the error as automatically repairable.
  5. The path is extracted from the message without authorization or ownership checks.
  6. The monitor runs chmod +x on the selected file.

Impact Assessment

The monitor can make any matching file ac ...[truncated 565 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not automatically modify file permissions based solely on text extracted from a job message.

  • Require explicit operator confirmation before changing executable permissions.

  • Define one or more approved script directories and reject paths outside them.

  • Resolve the canonical path with fs.realpathSync() and verify that it remains under an approved directory after resolving symbolic links.

  • Use fs.lstatSync() to reject symbolic links and non-regular files.

  • Verify expected ownership and current permission state before applying a change.

  • Use the filesystem API instead of invoking a shell:

    js
    const resolvedPath = fs.realpathSync(scriptPath);
    const stat = fs.lstatSync(resolvedPath);
    
    if (!stat.isFile() || stat.isSymbolicLink()) {
      throw new Error('The target must be a regular, non-symbolic-link file');
    }
    
    fs.chmodSync(resolvedPath, stat.mode | 0o100);
    
  • Record the original mode and provide a tested rollback operation.

  • Run the monitor with access only to the specific script directories it is expected to repair.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code extracts a filesystem path from job-controlled payload content and executes chmod +x on it via execSync, giving the skill the ability to alter permissions on arbitrary matching files. In the context of a failure monitor, this is overly powerful and dangerous because a crafted job payload can trigger unauthorized permission changes on local scripts outside the intended repair scope.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill explicitly instructs users to run shell commands and references local scripts, cron management, chmod, cat, and node execution, yet it declares no tool scope or permissions boundaries. In an auto-repair skill that can modify job configuration and filesystem permissions, missing explicit capability restrictions increases the risk of overbroad command execution and unintended system changes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The command example explicitly instructs the skill to use Chinese in its report output (报告格式用中文). This is a natural-language locale constraint presented without any user choice or justification that the skill is region-specific, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The security section claims the skill only fixes configuration issues and does not modify code, but earlier content documents changing script execute permissions with chmod +x. This mismatch can mislead operators about the real behavior of the skill, causing them to grant trust or autonomy they would not otherwise allow.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This manifest description says the skill is an "Automated failure detection, diagnosis, and auto-repair system for cron jobs" but does not specify when auto-repair is triggered, what failures qualify, or any exclusions. In a manifest file, that lack of trigger specificity can cause overly broad or unintended invocation expectations for a self-healing skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Permission modification is performed automatically with no user confirmation, despite being a privileged system-changing action. In this skill's context, auto-repair is expected, but changing executable bits on files can materially alter what code can run, so doing so without approval increases the chance of unsafe or unintended state changes.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill advertises human confirmation for sensitive cases, but the implementation only prints a message and never actually sends a notification or waits for approval. In an auto-repair system, this creates a dangerous mismatch between documented safety behavior and real behavior, causing operators to believe human review exists when it does not.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The natural-language descriptions in this JSON file are written only in Chinese (for example at L10, L18, and L23), which imposes a specific language choice without any indication of user opt-in or that the skill is intended solely for a Chinese-speaking context. This matches the policy category for language or locale constraints expressed in natural-language content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill hard-codes toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }) and all user-facing status/notification text is in Chinese. This enforces a specific language/locale choice without offering the user a preference or documenting that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/monitor.cjs:234