Back to skill

Security audit

World Meeting Coordination Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward local meeting-window helper with disclosed settings storage, though users should avoid invalid numeric options that can hang the script.

Install only if you are comfortable with the skill saving your meeting timezone, hours, and flexibility in its disclosed OpenClaw config file. Confirm setup/update requests before changing settings, and use positive values for --step, --duration, and --top until input validation is added.

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/meeting_windows.py:131
Finding

Unbounded Resource Consumption Through Unvalidated Step Size

Content
View full analysis

Vulnerability Details

File Location: scripts/meeting_windows.py, lines 131 and 195–211
Vulnerability Type: Improper input validation leading to uncontrolled resource consumption
Risk Level: Medium

Vulnerable Code

python
ap.add_argument("--step", type=int, default=60)
python
slots = []
t = start_day
end_day = start_day + timedelta(days=1)
while t < end_day:
    t2 = t + timedelta(minutes=args.duration)
    score = 0
    reasons = []
    rows = []
    for p in participants:
        ls, le = t.astimezone(p.tz), t2.astimezone(p.tz)
        pref_start, pref_end = hours_map.get(p.name, default_hours)
        flex = me_flex if p.name in hours_map and (pref_start, pref_end) == hours_map.get(p.name) else "balanced"
        pen = penalty(ls, pref_start, pref_end, flex)
        score += pen
        r = reason_for_penalty(p.name, pen, ls)
        if r:
            reasons.append(r)
        rows.append((p.name, ls, le))
    slots.append((classify(score), score, t, t2, rows, sorted(set(reasons))))
    t += timedelta(minutes=args.step)

Technical Analysis

The --step argument is parsed as an arbitrary integer but is never checked to ensure that it is positive. The loop terminates only when t reaches end_day, and its sole progress operation is:

python
t += timedelta(minutes=args.step)

If --step 0 is supplied, t never changes. If a negative step is supplied, t moves farther away from end_day. In both cases, the loop cannot terminate normally and continuously appends generated slot records to the slots list.

This creates an uncontrolled resource-consumption condition involving sustained CPU use and unbounded memory growth. The vulnerability is reachable directly through documented CLI execution when an untrusted caller can influence arguments.

Attack Path

  1. An attacker or untrusted caller invokes the meeting-window script.

...[truncated 1331 chars]

Remediation
View remediation

Remediation Suggestions

Validate numeric CLI arguments before any processing. At minimum, require --step to be greater than zero. A reusable argparse validator can reject invalid input before entering the loop:

python
def positive_int(value: str) -> int:
    parsed = int(value)
    if parsed <= 0:
        raise argparse.ArgumentTypeError("value must be a positive integer")
    return parsed

ap.add_argument("--step", type=positive_int, default=60)
ap.add_argument("--duration", type=positive_int, default=60)
ap.add_argument("--top", type=positive_int, default=3)

Apply reasonable upper and lower bounds as appropriate for the intended interface. For example, constrain slot step and duration values to a supported scheduling range and cap the number of generated slots independently of user input.

Add a defensive iteration limit so future logic changes cannot create another unbounded loop:

python
max_slots = 1440
generated = 0

while t < end_day and generated < max_slots:
    # Generate slot.
    t += timedelta(minutes=args.step)
    generated += 1

Add automated tests confirming that zero and negative values are rejected promptly and do not start slot generation. If this CLI is invoked by a service, also enforce process-level timeouts and memory limits as defense in depth.

Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (3)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The listed alternate setup phrases are broad enough that normal user requests about scheduling preferences or timezones could be misclassified as a configuration/setup command. That can cause unintended writes to local configuration or trigger an unexpected onboarding flow, which is a real safety and integrity issue even though it is not a code-execution bug.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises capabilities that involve reading and writing a user-scoped config file, but it does not explicitly declare any tool scope or permissions boundary in the manifest. That creates an authorization ambiguity: an agent or platform may permit broader file access than the skill actually needs, increasing the risk of unintended local file access or persistence.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/meeting_windows.py (reported line 140)May include surrounding context.

python
cfg = load_config()

    if args.setup or (not cfg and __import__("sys").stdin.isatty()):
        cfg = run_onboarding_interactive()

    if args.show_settings: