T09 · Insecure Skill Coding Practices
- 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: HighVulnerable 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.idandjob.delivery.tofrom the external OpenClawjobs.jsonfile and directly interpolates these values into commands passed toexecSync(). Node.js executes string commands through a shell, so shell metacharacters contained in these fields can alter the intended command.Placing
job.delivery.toinside 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.idis 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
- An attacker gains the ability to create or modify an entry in the OpenClaw cron
jobs.jsonfile. - The attacker inserts shell syntax into
job.idorjob.delivery.to. - The attacker configures the job state with an error message such as
job execution timed outorChannel is required. - The monitor identifies the job as failed and selects the corresponding automatic repair.
- The malicious field is interpolated into a command string.
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]
- An attacker gains the ability to create or modify an entry in the OpenClaw cron
- Remediation
View remediation
Remediation Suggestions
-
Replace shell-based
execSync()calls withexecFileSync()orspawnSync()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.idagainst 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.
-
