Back to skill

Security audit

Cron Health Cron

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed OpenClaw cron health-check kit with consent-gated scheduling and read-only routine checks, but users should harden the local command PATH before recurring use.

Before installing or scheduling this skill, review the config paths, run it as a low-privilege account, validate redaction on real logs, and harden command execution by using a trusted PATH or a local derivative that resolves and verifies the intended openclaw, crontab, and systemctl binaries.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/openclaw_cron_health_check.py:125
Finding

Allowlisted diagnostic commands are vulnerable to executable PATH hijacking

Content
View full analysis

Vulnerability Details

File Location: scripts/openclaw_cron_health_check.py:125-143 and scripts/openclaw_cron_health_check.py:177
Vulnerability Type: Untrusted executable resolution through the inherited PATH
Risk Level: Medium

Vulnerable Code

python
def validate_runnable_command(command: Any, cfg: dict[str, Any]) -> tuple[list[str], str | None]:
    argv, cwd = command_argv(command)
    base = os.path.basename(argv[0])
    if base in BLOCKED_BINS:
        raise ValueError(f"blocked command: {base}")
    if argv[0].startswith("/"):
        raise ValueError("absolute command paths are not supported by the portable checker")
    if not is_safe_builtin_argv(argv):
        raise ValueError(f"argv is not in the non-mutating diagnostic allowlist: {command_label(command)}")
    return argv, cwd


def run(command: Any, cfg: dict[str, Any], timeout: int = 20) -> tuple[int, str, str]:
    try:
        argv, cwd = validate_runnable_command(command, cfg)
        proc = subprocess.run(
            argv,
            check=False,
            text=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            timeout=timeout,
            cwd=cwd,
        )

The command existence check uses the same environment-dependent resolution:

python
return ("OK", "binary exists") if shutil.which(argv[0]) else ("CRITICAL", f"binary missing: {argv[0]}")

Technical Analysis

The checker restricts command arguments to fixed, non-mutating forms, including openclaw, crontab, and systemctl. This effectively prevents arbitrary command selection through the configuration. However, it executes these commands by bare executable name and therefore delegates executable resolution to the inherited PATH.

Absolute executable paths are explicitly rejected, while the script does not:

  • Replace PATH with a trusted, minimal search path.
  • Verify that th ...[truncated 2575 chars]
Remediation
View remediation

Remediation Suggestions

  1. Resolve each permitted utility to a trusted absolute path during installation or setup, such as a deployment-specific path for openclaw and platform-appropriate paths for crontab and systemctl.
  2. Permit absolute paths only after validating that the resolved basename and complete argument vector match the intended allowlist.
  3. Verify that each executable:
    • Is a regular file.
    • Is owned by root or another explicitly trusted account.
    • Is not writable by group or other users.
    • Resides under directories that are also not writable by untrusted users.
  4. Execute the verified absolute path rather than resolving the command name again through PATH.
  5. Pass a minimal sanitized environment to subprocess.run(). At minimum, define a trusted PATH and remove environment variables capable of altering executable or library loading.
  6. Fail closed if a utility cannot be resolved uniquely to an approved path.
  7. Document the resolved executable paths in the instance-specific configuration and verify them during the manual pre-scheduling validation.
  8. Run the recurring health check using a dedicated, non-privileged account with read access only to the metadata and logs necessary for the report.
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/openclaw_cron_health_check.py` for the deterministic checker

Lp1

High
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The script can execute local system commands through subprocess.run(), including openclaw, crontab, and systemctl, based on configuration input. Although the implementation uses a narrow allowlist and avoids shell execution, this still constitutes shell/process-execution capability that must be declared; otherwise the skill can perform actions beyond its advertised permission model and may leak system state via command output.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The script can execute local system commands through subprocess.run(), including openclaw, crontab, and systemctl, based on configuration input. Although the implementation uses a narrow allowlist and avoids shell execution, this still constitutes shell/process-execution capability that must be declared; otherwise the skill can perform actions beyond its advertised permission model and may leak system state via command output.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 · SKILL.md (reported line 4)May include surrounding context.

md
---
name: "cron-health-cron"
description: "Create portable OpenClaw cron health checks with deterministic scripts, config, validation, and reports."
metadata: { "openclaw": { "requires": { "bins": ["python3", "openclaw", "crontab", "systemctl"] }, "permissions": { "filesystem": ["read configured cron files, scheduler metadata files, registry notes, callback notes, and log files"], "commands": ["run bundled Python checker", "run fixed non-mutating argv probes: openclaw cron list --json, crontab -l, systemctl --failed --no-pager --plain, systemctl list-timers --all --no-pager --plain, systemctl is-active <service>"], "network": "none", "writes": "none during routine health checks" } } }
allowed-tools: ["exec"]
---

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 · SKILL.md (reported line 55)May include surrounding context.

md
---
name: "cron-health-cron"
description: "Create portable OpenClaw cron health checks with deterministic scripts, config, validation, and reports."
metadata: { "openclaw": { "requires": { "bins": ["python3", "openclaw", "crontab", "systemctl"] }, "permissions": { "filesystem": ["read configured cron files, scheduler metadata files, registry notes, callback notes, and log files"], "commands": ["run bundled Python checker", "run fixed non-mutating argv probes: openclaw cron list --json, crontab -l, systemctl --failed --no-pager --plain, systemctl list-timers --all --no-pager --plain, systemctl is-active <service>"], "network": "none", "writes": "none during routine health checks" } } }
allowed-tools: ["exec"]
---

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/openclaw_cron_health_check.py (reported line 150)May include surrounding context.

python
def run(command: Any, cfg: dict[str, Any], timeout: int = 20) -> tuple[int, str, str]:
    try:
        argv, cwd = validate_runnable_command(command, cfg)
        proc = subprocess.run(
            argv,
            check=False,
            text=True,

Static analysis

No suspicious patterns detected.