Back to skill

Security audit

Cron Local

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local reminder schedule manager that stores schedule data on the user's machine and does not show evidence of network sync, hidden execution, or credential access.

Install only if you are comfortable with reminders, notes, and tags being stored locally under ~/.openclaw/workspace/memory/cron. Confirm before allowing the agent to create or modify jobs, override the timezone if Asia/Tokyo is not correct for you, and avoid putting highly sensitive details in job notes unless your local account and home directory permissions are protected.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/storage.py:24
Finding

Schedule data files are created without enforced restrictive permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/init_storage.py:11-14; scripts/lib/storage.py:24-29
Vulnerability Type: Insecure local file permissions
Risk Level: Medium

Vulnerable Code

scripts/init_storage.py:11-14

python
def write_json_if_missing(path, payload):
    if not os.path.exists(path):
        with open(path, "w", encoding="utf-8") as f:
            json.dump(payload, f, indent=2, ensure_ascii=False)

scripts/lib/storage.py:24-29

python
def _atomic_save(path, data):
    ensure_dir()
    tmp = path + ".tmp"
    with open(tmp, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    os.replace(tmp, path)

Technical Analysis

The Skill stores job titles, notes, tags, schedule metadata, and run information in JSON files under ~/.openclaw/workspace/memory/cron. Both initial creation and subsequent atomic saves rely exclusively on process-default permissions.

The code does not explicitly enforce mode 0600 on data files or mode 0700 on the storage directory. Consequently, the effective permissions depend on the caller's umask and existing parent-directory configuration. In an environment with a permissive umask, other local users may be able to read schedule data.

Atomic updates create a new fixed-name temporary file and replace the destination with it. The replacement file inherits the temporary file's newly derived permissions rather than preserving a previously hardened destination mode.

Attack Path

  1. A user runs the Skill in an environment with a permissive umask or inadequately protected parent directories.
  2. The user creates a schedule containing private information in its title, notes, tags, or timing metadata.
  3. init_storage.py or _atomic_save() creates the corresponding JSON file without explicitly restrictive permissions.
  4. Another local account examines ~/.openclaw/workspace/memory/cron.

...[truncated 703 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the storage directory with mode 0700 and verify its ownership before use.
  • Create data and temporary files with mode 0600, independent of the process umask.
  • Apply os.chmod(path, 0o600) to existing files after validating that they are owned by the expected user.
  • Use secure, exclusive temporary-file creation, such as tempfile.mkstemp() in the destination directory.
  • Flush and synchronize the temporary file before replacement when durability is required.
  • Verify that destination and temporary paths are regular files and are not unexpected symbolic links.
  • Preserve restrictive permissions across atomic replacements.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/add_job.py:49
Finding

Truncated UUID job identifiers can silently overwrite existing jobs

Content
View full analysis

Vulnerability Details

File Location: scripts/add_job.py:49; scripts/add_job.py:81-83
Vulnerability Type: Insufficient identifier entropy and missing collision detection
Risk Level: Medium

Vulnerable Code

scripts/add_job.py:49

python
job_id = f"JOB-{str(uuid.uuid4())[:4].upper()}"

scripts/add_job.py:81-83

python
data = load_jobs()
data["jobs"][job_id] = job
save_jobs(data)

Technical Analysis

Although the code generates a UUIDv4 value, it retains only the first four hexadecimal characters. This produces an identifier space of only 65,536 possible values.

The generated identifier is used directly as a dictionary key without checking whether it already exists. If a collision occurs, the assignment replaces the existing job object in memory, and save_jobs() persists that replacement. No warning, confirmation, retry, or backup is performed.

Under the birthday paradox, collision probability increases substantially as the number of generated jobs grows. An actor capable of repeatedly invoking add_job.py can accelerate this condition, although selecting a particular victim identifier remains probabilistic because UUID generation is random.

Attack Path

  1. A valid existing job is stored under an identifier such as JOB-ABCD.
  2. A user or automated process repeatedly invokes add_job.py.
  3. A newly generated UUID eventually has the same first four hexadecimal characters as an existing job.
  4. The code executes data["jobs"][job_id] = job without detecting the collision.
  5. The existing job is silently replaced by the newly supplied title, schedule, notes, and other fields.
  6. save_jobs(data) commits the data loss to jobs.json.

Exploitation requires permission to invoke the local job-creation workflow and write the Skill's storage files. The collision is probabilistic rather than a deterministic overwrite of a selected job.

Impact Assessment

A ...[truncated 396 chars]

Remediation
View remediation

Remediation Suggestions

  • Use the complete UUID value as the persistent job identifier.
  • If short human-readable identifiers are required, use substantially more entropy and check for collisions before insertion.
  • Generate identifiers only after loading current jobs, and retry while the candidate identifier already exists.
  • Refuse to overwrite an existing dictionary key unless the caller explicitly requests an update operation.
  • Save a recoverable backup or maintain an append-only change history for critical schedule records.
  • Add automated tests that force duplicate identifiers and verify that existing jobs remain unchanged.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The skill advertises capabilities such as natural-language schedule capture, pause/resume, job inspection, and recurring schedule storage, but the analyzed behavior reportedly does not implement those functions. This mismatch is dangerous because users and orchestrators may trust the skill to manage time-based actions correctly when it may silently fail, mis-schedule, or omit expected controls like pause/resume.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill declares local file storage and references multiple scripts that read and write under the user's home directory, but it does not declare any explicit tool scope or permissions boundary. That omission can cause the agent to invoke file-capable behavior without clear user-visible constraints, increasing the risk of unintended file access or modification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The description uses very broad activation cues like recurring timing, schedules, cadence, and weekly/daily/monthly routines, which can cause the skill to trigger on ordinary planning conversations. Unintended activation is risky here because the skill has local file-writing behavior and may create or alter persistent schedule state when the user did not intend to invoke it.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script sets --timezone to Asia/Tokyo by default, which imposes a specific locale assumption on all users unless they explicitly override it. This is a natural-language policy concern because the file provides no user opt-in, choice prompt, or documented regional justification for that default.

Content

No source excerpt is available for this finding.