Back to skill

Security audit

Sleep Routine Coach

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for local sleep coaching, but its all-data deletion command can delete an arbitrary chosen directory if misused.

Review this skill before installing if you plan to use deletion controls. It appears intended for private local sleep coaching and consented reminders, but the all-data deletion script should only ever be run against the real sleep-routine data directory; a safer version would validate an app-owned directory and delete only known app files.

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

Error
Location
scripts/manage_profile.py:281
Finding

Unrestricted Recursive Deletion Through User-Controlled Data Directory

Content
View full analysis

Vulnerability Details

File Location: scripts/manage_profile.py, lines 281–295
Vulnerability Type: Unrestricted recursive deletion of an arbitrary directory
Risk Level: High

Vulnerable Code

python
def cmd_delete_all(args: argparse.Namespace) -> None:
    if not args.confirm:
        raise SleepRoutineError("Deletion requires --confirm")
    removed = []
    if args.data_dir.exists():
        for child in args.data_dir.iterdir():
            if child.is_file():
                child.unlink()
                removed.append(child.name)
            elif child.is_dir():
                shutil.rmtree(child)
                removed.append(child.name + "/")
        try:
            args.data_dir.rmdir()
        except OSError:
            pass
    print_json({"deleted": True, "removed": sorted(removed)})

The deletion target comes from the unrestricted global command-line argument declared at line 301:

python
parser.add_argument("--data-dir", type=Path, default=default_data_dir())

Technical Analysis

The delete-all operation assumes that args.data_dir is an application-owned sleep-data directory, but it does not verify this assumption. The caller can supply any filesystem path accessible to the current process.

The implementation enumerates every child of the supplied path. It invokes Path.unlink() for files and shutil.rmtree() for directories, regardless of whether those entries belong to this Skill. Consequently, the operation is not limited to the documented application files:

  • profile.json
  • sleep-records.json
  • reminders.json
  • sleep-shift-plan.json

The --confirm flag only acts as a mechanical Boolean gate. It does not prove that the resolved path is safe, belongs to the application, or matches a path that the user reviewed. There are also no checks rejecting filesystem roots, home directories, project roots, symbolic links, or directories lacking an application ownership marker.

Attack Path

...[truncated 1639 chars]

Remediation
View remediation

Remediation Suggestions

  1. Delete only explicitly owned files. Replace directory-wide enumeration with an allowlist:

    python
    OWNED_FILES = {
        "profile.json",
        "sleep-records.json",
        "reminders.json",
        "sleep-shift-plan.json",
    }
    
    for name in OWNED_FILES:
        target = args.data_dir / name
        if target.is_file():
            target.unlink()
    
  2. Add an application ownership marker. Create a marker during initialization and require it before any destructive operation. Validate its expected schema and application identifier.

  3. Canonicalize and validate the target. Resolve the path before deletion and reject:

    • Filesystem roots
    • The user's home directory
    • Repository or project roots
    • Paths outside an approved base directory
    • Symbolic links and paths traversing symbolic links
    • Directories without the ownership marker
  4. Bind confirmation to the resolved path. Require confirmation containing the canonical target path or a generated confirmation token, rather than accepting a generic --confirm flag.

  5. Preserve least-destructive behavior. Remove the data directory only if it contains no entries other than known application-owned files. Never recursively remove unknown subdirectories.

  6. Add security tests. Verify that deletion fails safely when --data-dir points to a home directory, root directory, repository, symlink, unmarked directory, or directory containing unknown files.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (9)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
nly for periodic, adaptive checks within configured active hours. Do not claim `SKILL.md` runs in the background.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
Do not persist partial answers before question 3 receives an explicit yes. Hold them only in the current conversation. If consent is declined, do not call a writing command.

Apply gentle defaults without asking: no fixed sleep-duration target, no wake reminder, no weekend split, no hydration reminder, gentle intensity, and an initial active window from 90 minutes before to 30 minutes after the sleep-time anchor. These are editable defaults, not medical recommendations.

Ask about wake time only when the user wants a wake or morning reminder. Ask about weekend differences, nocturia/hydration, intensity, or weekly summaries only when the user requests that feature or the setting becomes necessary.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/interaction-protocol.md (reported line 19)May include surrounding context.

md
Do not persist partial answers before question 3 receives an explicit yes. Hold them only in the current conversation. If consent is declined, do not call a writing command.

Apply gentle defaults without asking: no fixed sleep-duration target, no wake reminder, no weekend split, no hydration reminder, gentle intensity, and an initial active window from 90 minutes before to 30 minutes after the sleep-time anchor. These are editable defaults, not medical recommendations.

Ask about wake time only when the user wants a wake or morning reminder. Ask about weekend differences, nocturia/hydration, intensity, or weekly summaries only when the user requests that feature or the setting becomes necessary.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/interaction-protocol.md (reported line 39)May include surrounding context.

md
Do not persist partial answers before question 3 receives an explicit yes. Hold them only in the current conversation. If consent is declined, do not call a writing command.

Apply gentle defaults without asking: no fixed sleep-duration target, no wake reminder, no weekend split, no hydration reminder, gentle intensity, and an initial active window from 90 minutes before to 30 minutes after the sleep-time anchor. These are editable defaults, not medical recommendations.

Ask about wake time only when the user wants a wake or morning reminder. Ask about weekend differences, nocturia/hydration, intensity, or weekly summaries only when the user requests that feature or the setting becomes necessary.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring states 'never create Cron jobs or send messages,' implying the script only plans reminders. However, the code later constructs concrete openclaw cron create operations and returns them as scheduler requests for downstream execution, which is materially closer to job creation than the docstring suggests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

SQP-3 applies to all file types and covers language/locale policy issues. The example at L26 is written only in Chinese, while the surrounding guidance is in English, and the file does not state that the skill is region-specific or that users can opt into Chinese output.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The plan output says 'Preview only' and 'never executes OpenClaw or creates background jobs,' but this same script also includes commands to register, unregister, and list external jobs in persistent state. While it does not itself execute OpenClaw, the documentation presents the script as purely non-operative despite managing real job lifecycle metadata.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.