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## 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
## 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## 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
## 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
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.

Lp3

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.

Natural-Language Policy Violations

Medium
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.

Intent-Code Divergence

Medium
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.

Vague Triggers

Medium
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.

Missing User Warnings

Medium
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.

Description-Behavior Mismatch

Medium
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.

Natural-Language Policy Violations

Low
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.

Natural-Language Policy Violations

Low
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.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

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