Back to skill

Security audit

Smart Scheduler

Security checks for vulnerabilities and agentic risk

Overview

This scheduling skill is transparent about its purpose, but its calendar export can write to arbitrary local paths and overwrite files.

Install only if you are comfortable with a local scheduling helper that writes a SQLite ledger and exports calendar files. Keep exports under the skill's .runtime directory, avoid untrusted meeting text, and review output paths carefully because this version can overwrite writable files outside the skill folder.

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/smart_scheduler.py:182
Finding
Unescaped User-Controlled Values Permit ICS Content Injection## Vulnerability Details **File Location**: `scripts/smart_scheduler.py`, lines 182-195 **Vulnerability Type**: ICS content injection through insufficient output encoding **Risk Level**: Medium ### Vulnerable Code ```python contents = "\n".join( [ "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//OpenClaw Skill Suite//Smart Scheduler//EN", "BEGIN:VEVENT", f"UID:request-{args.request_id}@openclaw-skill-suite", f"SUMMARY:{booking['title']}", f"DTSTART;TZID={booking['timezone']}:{booking['chosen_start'].replace('-', '').replace(':', '')}", f"DTEND;TZID={booking['timezone']}:{booking['chosen_end'].replace('-', '').replace(':', '')}", f"DESCRIPTION:Organized by {booking['organizer']}; confirmed by {booking['confirmed_by']}", f"LOCATION:{booking['location'] or ''}", "END:VEVENT", "END:VCALENDAR", "", ] ) ``` ### Technical Analysis The ICS document is constructed by directly interpolating database values into RFC 5545 properties. Values such as the meeting title, organizer, timezone, location, confirmed participant, and proposed timestamps originate from command-line input and are not safely validated or encoded before serialization. RFC 5545 text values require escaping of backslashes, commas, semicolons, and newlines. Carriage-return or newline characters are particularly dangerous because they can terminate the intended property and introduce additional calendar properties or components. The timezone is inserted into a property parameter and requires stricter validation rather than ordinary text escaping. An attacker who can influence scheduling data could inject content such as additional event properties, attendees, alarms, or extra calendar components. The exact behavior after import depends on the ...[truncated 1236 chars]
Remediation
## Remediation Suggestions - Use a maintained RFC 5545 serialization library instead of manually concatenating ICS lines. - Escape text-property values according to RFC 5545, including backslashes, commas, semicolons, carriage returns, and newlines. - Reject all CR and LF characters in property parameters such as `TZID`. - Validate timezone identifiers against an approved IANA timezone database. - Parse proposed start and end values as date-time objects, verify that the end follows the start, and serialize them into a canonical ICS representation. - Apply RFC-compliant line folding where necessary. - Add tests covering CRLF injection and reserved characters in every exported field, including title, organizer, confirmer, location, timezone, and timestamps.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/smart_scheduler.py:180
Finding
Arbitrary Output Path Allows Existing Files and Symlink Targets to Be Overwritten## Vulnerability Details **File Location**: `scripts/smart_scheduler.py`, lines 180-197 **Vulnerability Type**: Unrestricted file write and unsafe overwrite behavior **Risk Level**: Medium ### Vulnerable Code ```python output = Path(args.output) if args.output else runtime_dir(args.base_dir) / f"request-{args.request_id}.ics" output.parent.mkdir(parents=True, exist_ok=True) contents = "\n".join( [ "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//OpenClaw Skill Suite//Smart Scheduler//EN", "BEGIN:VEVENT", f"UID:request-{args.request_id}@openclaw-skill-suite", f"SUMMARY:{booking['title']}", f"DTSTART;TZID={booking['timezone']}:{booking['chosen_start'].replace('-', '').replace(':', '')}", f"DTEND;TZID={booking['timezone']}:{booking['chosen_end'].replace('-', '').replace(':', '')}", f"DESCRIPTION:Organized by {booking['organizer']}; confirmed by {booking['confirmed_by']}", f"LOCATION:{booking['location'] or ''}", "END:VEVENT", "END:VCALENDAR", "", ] ) output.write_text(contents, encoding="utf-8") ``` ### Technical Analysis The `--output` argument is accepted as an unrestricted path. The implementation creates missing parent directories and calls `Path.write_text()`, which truncates an existing file before writing. It neither confines exports to the Skill's runtime directory nor checks whether the destination already exists. The destination is also not checked for symbolic links. Consequently, if the executing account can follow and write through a symlink, the operation can replace the symlink target. The practical reach is limited to paths writable by the account running the Skill; this issue does not bypass operating-system permissions or independently provide privilege escalati ...[truncated 1548 chars]
Remediation
## Remediation Suggestions - Use a dedicated export directory beneath `.runtime` and resolve the requested destination before writing. - Verify that the resolved destination remains beneath the approved export directory; reject absolute paths and traversal outside that directory. - Reject symbolic-link destinations and inspect path components where attacker-controlled directories are possible. - Create files atomically and exclusively by default, such as with `open("x")`, so existing files cannot be silently truncated. - Require an explicit `--overwrite` option and clear user confirmation before replacing an existing export. - Where stronger race resistance is required, use descriptor-based filesystem operations with no-follow and exclusive-create flags supported by the platform. - Avoid automatically creating arbitrary parent directory trees from an untrusted output value. - Add tests for absolute paths, `..` traversal, existing destinations, symbolic links, and overwrite refusal.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (5)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill exposes shell execution and file read/write behavior via documented Python commands, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an over-privileged integration surface where an agent may invoke capabilities beyond what a reviewer or runtime policy can narrowly constrain, increasing the risk of unintended file access, command execution, or network use if the implementation or future changes are unsafe.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The export_ics command accepts a user-supplied --output path and writes directly to it after creating parent directories, with no restriction that the destination stay inside the skill's runtime directory. This gives the skill an arbitrary file-write primitive within the permissions of the executing user, which exceeds the stated scheduling-ledger scope and can overwrite or place files in unrelated locations.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
Because args.output is passed to Path() and then written with write_text() without validation, the feature effectively exposes arbitrary file creation/overwrite anywhere the process can access. Even though the content is an ICS file, uncontrolled write location can be abused to clobber application files, drop misleading artifacts, or interfere with other local data.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The export_ics command creates directories and writes an .ics file containing meeting metadata such as title, organizer, confirmation details, and location. This is a file-write operation affecting user data, but the code provides no confirmation prompt, warning comment/docstring, or user-facing disclosure before performing the write.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
self.temp_dir.cleanup()

    def run_cli(self, *args):
        result = subprocess.run(
            [sys.executable, str(self.base_dir / "scripts" / "smart_scheduler.py"), *self.base_arg, *args],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.