Back to skill

Security audit

session-cleanup

Security checks for vulnerabilities and agentic risk

Overview

This cleanup skill has a legitimate purpose, but its batch cleanup script can remove packages and skill directories with weaker safeguards than the skill promises.

Review before installing. This skill is meant to clean session leftovers, but only use it if you are comfortable with a tool that can delete files, uninstall packages, and remove skill directories. Avoid one-click cleanup, inspect the session-track file before execution, and do not allow package or skill removal unless the exact items and paths are shown and confirmed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/cleanup.py:493
Finding

Cleanup Workflow Bypasses Confirmation for Packages and Skills

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:123-127, SKILL.md:150-181, scripts/cleanup.py:493-515
Vulnerability Type: Missing authorization check before destructive operations
Risk Level: High

The documented cleanup workflow invokes cleanup.py using the complete tracking file before obtaining the explicit confirmation required for dependency and Skill removal.

Relevant workflow instructions:

markdown
- **6+ items** → Agent runs `cleanup.py` in two phases:
  1. **Preview**: `python "<skill_dir>/scripts/cleanup.py" --track-file "<workspace>/.workbuddy/session-track.json" --dry-run`
  2. **Execute**: `python "<skill_dir>/scripts/cleanup.py" --track-file "<workspace>/.workbuddy/session-track.json"`
- **User explicitly requests one-click cleanup** → Use `cleanup.py` regardless of item count.

The later confirmation requirement states:

markdown
For each Class B item, present a grouped confirmation prompt:

- If user replies **全部删除** → uninstall/remove all Class B items.
- If user replies **全部保留** → skip all, close the log.
- If user replies **逐一确认** → iterate through each item and ask individually.

The invoked CLI nevertheless processes all Class B entries automatically:

python
if args.track_file:
    track_path = Path(args.track_file)
    if not track_path.exists():
        print(f"❌ session-track.json not found: {args.track_file}", file=sys.stderr)
        sys.exit(2)
    manifest, workspace = load_track_as_manifest(str(track_path))

    if manifest.get("temp_files"):
        print("\n── Temp Files ──")
        summary["temp_files"] = delete_files(
            manifest["temp_files"], dry_run, workspace=workspace
        )

    if manifest.get("pip_packages"):
        print("\n── Pip Packages ──")
        summary["pip"] = uninstall_pip(manifest["pip_packages"], dry_run)

    if manifest.get("npm_packages"):
        print("\n─
...[truncated 2067 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make --track-file process only temp_files by default.
  2. Require explicit flags for every destructive Class B category, such as:
    • --confirmed-pip
    • --confirmed-npm
    • --confirmed-skills
  3. Generate a separate approval manifest containing only the canonical resources displayed to and approved by the user.
  4. Bind confirmation to a digest of the approved manifest so the tracking file cannot be changed between preview and execution.
  5. Re-display canonical paths and package names immediately before execution.
  6. Refuse to process Class B resources in unattended or one-click mode unless explicit confirmation is supplied.
  7. Add regression tests proving that a normal --track-file cleanup never removes packages or Skills.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cleanup.py:313
Finding

Unrestricted Skill Path Permits Arbitrary Recursive Directory Deletion

Content
View full analysis

Vulnerability Details

File Location: scripts/cleanup.py:313-334
Vulnerability Type: Unvalidated path used in recursive deletion
Risk Level: High

The Skill deletion function accepts an arbitrary directory path and passes it directly to shutil.rmtree():

python
def delete_skills(skill_paths: list[str], dry_run: bool = False) -> dict:
    """Delete skill directories. Same logic as delete_files but with extra warning."""
    results = {"deleted": [], "skipped": [], "failed": []}
    for raw in skill_paths:
        p = Path(raw)
        if not p.exists():
            results["skipped"].append({"path": raw, "reason": "does not exist"})
            continue
        if not p.is_dir():
            results["skipped"].append({"path": raw, "reason": "not a directory"})
            continue
        if dry_run:
            print(f"  🔍 DRY-RUN would delete skill: {raw}")
            results["deleted"].append(raw)
            continue
        try:
            shutil.rmtree(p)
            print(f"  ✅ Skill deleted: {raw}")
            results["deleted"].append(raw)
        except Exception as e:
            print(f"  ❌ Failed to delete skill: {raw}  [{e}]")
            results["failed"].append({"path": raw, "reason": str(e)})
    return results

Technical Analysis

delete_skills() verifies only that the supplied path exists and is a directory. It does not:

  • Resolve and validate the canonical path.
  • Require the directory to reside under an approved .workbuddy/skills root.
  • Reject home directories, workspace roots, project directories, or filesystem roots.
  • Reuse is_safe_to_delete().
  • Confirm that the final path component is an installed Skill.
  • Reject symlinked Skill paths or protect against path replacement between validation and deletion.

The function's docstring claims that it uses the same logic as delete_files(), but no corresponding safety validation i ...[truncated 1113 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define explicit approved Skill roots, such as the canonical user-level and workspace-level .workbuddy/skills directories.
  2. Resolve both the approved root and requested target with strict canonicalization.
  3. Require the target to be an immediate child of an approved Skill root.
  4. Reject the approved root itself, filesystem roots, home directories, project roots, and empty or relative ambiguous paths.
  5. Reject symlinks and revalidate the target immediately before deletion.
  6. Require explicit user confirmation of the canonical path.
  7. Prefer trash or quarantine over immediate shutil.rmtree() deletion.
  8. Apply the same protected-root controls used for ordinary file deletion.
  9. Add tests for project roots, home directories, traversal paths, symlinks, junctions, and Skill-root deletion attempts.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cleanup.py:174
Finding

Unescaped File Path Allows AppleScript Injection on macOS

Content
View full analysis

Vulnerability Details

File Location: scripts/cleanup.py:174-185
Vulnerability Type: AppleScript code injection
Risk Level: High

The macOS trash implementation embeds an untrusted path directly into AppleScript source:

python
elif system == "Darwin":
    result = subprocess.run(
        ["osascript", "-e",
         f'tell app "Finder" to delete POSIX file "{str(p)}"'],
        capture_output=True, text=True, timeout=15
    )
    if result.returncode == 0:
        return True, "moved to Trash"
    if allow_hard_delete and _is_temp_path(p):
        _direct_remove(p)
        return True, "direct removal (temp path, trash unavailable)"
    return False, f"failed to move to Trash (exit code {result.returncode})"

Technical Analysis

Passing arguments as a list prevents shell metacharacter interpretation, but it does not prevent injection into the language interpreted by osascript. The value of str(p) is embedded between double quotes in dynamically generated AppleScript source without escaping AppleScript quotes, backslashes, or control characters.

macOS filenames can contain characters that terminate the quoted AppleScript string. A crafted filename can therefore alter the generated AppleScript program and append additional statements. The script is executed under the current Agent user's permissions.

Attack Path

  1. An attacker creates a file or directory in an allowed temporary location with a name containing AppleScript string delimiters and injected AppleScript statements.
  2. The crafted path is added to temp_files, other, or supplied through --paths.
  3. Cleanup passes the safety check because the object resides under an allowed temporary root.
  4. send_to_trash() interpolates the path into the osascript -e source string.
  5. osascript parses the injected content as part of the program.
  6. The injected AppleScript executes with the Agent process's user privil ...[truncated 664 chars]
Remediation
View remediation

Remediation Suggestions

Do not interpolate the path into AppleScript source. Pass it as a separate osascript argument and read it from argv, for example:

python
script = """
on run argv
    set targetPath to item 1 of argv
    tell application "Finder"
        delete POSIX file targetPath
    end tell
end run
"""
result = subprocess.run(
    ["osascript", "-e", script, str(p)],
    capture_output=True,
    text=True,
    timeout=15,
)

Additional hardening should include:

  1. Prefer a native trash API that does not interpret source code.
  2. Reject paths containing null bytes and normalize paths before validation.
  3. Ensure the canonical path remains within the approved root.
  4. Add macOS tests using filenames containing quotes, backslashes, newlines, Unicode, and AppleScript syntax.
  5. Verify that only the intended file is moved to Trash during adversarial filename tests.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cleanup.py:61
Finding

Denylist Safety Model Allows Deletion from Arbitrary Windows Drives

Content
View full analysis

Vulnerability Details

File Location: scripts/cleanup.py:61-130
Vulnerability Type: Incomplete path authorization and unsafe default allow
Risk Level: High

The deletion safety check uses a limited protected-root denylist and allows any path that does not match it:

python
FORBIDDEN_ROOTS = [
    Path.home(),
    Path.home() / "Desktop",
    Path.home() / "Downloads",
    Path.home() / "Documents",
    Path("C:/"),
    Path("C:/Windows"),
    Path("C:/Program Files"),
    Path("C:/Program Files (x86)"),
    Path("/"),
    Path("/usr"),
    Path("/etc"),
    Path("/bin"),
]

ALLOWED_TEMP_ROOTS = [
    Path(os.environ.get("TEMP", "C:/Windows/Temp")),
    Path(os.environ.get("TMP", "C:/Windows/Temp")),
    Path("/tmp"),
    Path.home() / "AppData" / "Local" / "Temp",
]

def is_safe_to_delete(p: Path, workspace: str = "") -> tuple[bool, str]:
    """Return (safe, reason). Only allow deletions under known temp/generated paths."""
    resolved = p.resolve()

    if workspace:
        ws = Path(workspace).resolve()
        try:
            rel = resolved.relative_to(ws)
            rel_str = str(rel).replace("\\", "/")
            for subdir in ALLOWED_SUBDIRS:
                if rel_str.startswith(subdir + "/") or rel_str == subdir:
                    return True, f"under workspace disposable dir: {subdir}"
            return False, (
                "workspace file (not a disposable subdir): "
                "use delete_file tool instead"
            )
        except ValueError:
            pass

    for forbidden in FORBIDDEN_ROOTS:
        if sys.platform == "win32" and str(forbidden) in ("/", "\\"):
            continue
        try:
            resolved.relative_to(forbidden.resolve())
            for allowed in ALLOWED_TEMP_ROOTS:
                try:
                    resolved.relative_to(allowed.resolve())
                    return True,
...[truncated 2431 chars]
Remediation
View remediation

Remediation Suggestions

Replace the denylist with a fail-closed allowlist:

  1. Return False unless the canonical target is under:
    • A canonical operating-system temporary root, or
    • An explicitly approved disposable workspace directory.
  2. Require --workspace for manifest cleanup involving workspace paths.
  3. Reject non-temp --paths targets unless an explicit confirmation mode is used.
  4. Enumerate and canonicalize Windows volume roots dynamically rather than protecting only C:.
  5. Handle UNC paths, mapped drives, junctions, mount points, and symlinks explicitly.
  6. Revalidate the canonical target immediately before deletion to reduce path-replacement races.
  7. Require generated directories to be descendants of the exact workspace root.
  8. Change the final branch to:
python
return False, "path is not under an approved deletion root"
  1. Reverse the existing test expectation so arbitrary non-temp paths without workspace context must be rejected.
  2. Add tests covering secondary drives, UNC shares, mapped volumes, junctions, sibling workspaces, and omitted workspace arguments.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (47)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Skills | `init_skill.py`, `use_skill`, manually writing a new `SKILL.md` to a skills folder |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **6+ items** → Agent runs `cleanup.py` in two phases:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **6+ items** → Agent runs `cleanup.py` in two phases:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **6+ items** → Agent runs `cleanup.py` in two phases:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/cleanup-guide.md (reported line 30)May include surrounding context.

osascript -e 'tell app "Finder" to delete POSIX file "/path/to/file"'

Direct remove (temp only)

rm -rf /tmp/mysession/

text

### Linux (Bash)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/cleanup-guide.md (reported line 43)May include surrounding context.

osascript -e 'tell app "Finder" to delete POSIX file "/path/to/file"'

Direct remove (temp only)

rm -rf /tmp/mysession/

text

### Linux (Bash)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/cleanup-guide.md (reported line 30)May include surrounding context.

osascript -e 'tell app "Finder" to delete POSIX file "/path/to/file"'

Direct remove (temp only)

rm -rf /tmp/mysession/

text

### Linux (Bash)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/cleanup-guide.md (reported line 43)May include surrounding context.

osascript -e 'tell app "Finder" to delete POSIX file "/path/to/file"'

Direct remove (temp only)

rm -rf /tmp/mysession/

text

### Linux (Bash)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding is valid because the recursive deletion targets a location under '~', which the guide itself later says should never be auto-deleted broadly. Even though the intent is to remove a specific skill directory, presenting a raw rm -rf home-subpath command in an agent-facing guide increases the chance of unintended destructive deletion if path handling is imperfect.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 145)May include surrounding context.

Remove-Item -Path "$env:USERPROFILE.workbuddy\skills\skill-name" -Recurse -Force

macOS/Linux

rm -rf ~/.workbuddy/skills/skill-name/

text

To list installed user skills:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

This duplicate finding is valid because the recursive deletion targets a location under '~', which the guide itself later says should never be auto-deleted broadly. Even though the intent is to remove a specific skill directory, presenting a raw rm -rf home-subpath command in an agent-facing guide increases the chance of unintended destructive deletion if path handling is imperfect.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 145)May include surrounding context.

Remove-Item -Path "$env:USERPROFILE.workbuddy\skills\skill-name" -Recurse -Force

macOS/Linux

rm -rf ~/.workbuddy/skills/skill-name/

text

To list installed user skills:

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

delete_skills() recursively removes any directory listed in skill_paths via shutil.rmtree() and does not call is_safe_to_delete() or enforce any allowed root. Because the track file or manifest is attacker-controllable input in this threat model, a crafted entry could cause arbitrary recursive deletion of sensitive directories, making this especially dangerous in a cleanup skill whose purpose is destructive operations.

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 · README.md (reported line 84)May include surrounding context.

md
## Safety Rules

1. Never auto-delete files outside temp/scratch/generated paths without confirmation
2. Never delete workspace source code, project configuration, or `.workbuddy/` directory
3. Never use `rm -rf` or `del /S /Q` on home, desktop, downloads, or project roots
4. Skills deletion is permanent — always warn before removing

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill describes file deletion, package uninstall, skill removal, and shell command execution, but it does not declare any explicit tool scope or allowed-tools boundary. In practice this increases the blast radius of ambiguous or over-permissive agent execution, because a cleanup skill inherently touches destructive capabilities and there is no machine-readable restriction limiting what tools it may invoke.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The start-tracking trigger list contains broad natural-language phrases such as 'session cleanup' and '帮我清理' that commonly appear in ordinary conversation. This can cause unintended activation of persistent tracking and later destructive cleanup behavior without a clearly delimited opt-in, especially in multilingual contexts where the phrases are generic.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The cleanup trigger phrases are also broad and include generic requests like 'clean up', '帮我清理', and '会话清理'. Because this phase can directly delete files and uninstall software, ambiguous activation is more dangerous here than in tracking mode and can lead to destructive actions from conversational wording rather than an intentional command.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The instruction to classify items and delete Class A items 'without asking' authorizes autonomous destructive decisions based on heuristics like path patterns and keywords. Misclassification can delete user-valued files, and the danger is amplified by generic triggers, persistent tracking, and shell-based deletion outside the workspace.

Content

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

md
For each tracked item, classify it as either:

- **A: Safe to auto-delete** — files with no dependencies (temp files, demo scripts, test outputs, generated images). These are deleted without asking.
- **B: Requires confirmation** — installed packages, Skills, or system software that may have dependencies or ongoing utility. These require explicit user consent.

#### Step C · Auto-delete safe items (Class A)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill text permits automatic deletion of Class A items and explains the mechanics, but it does not present a strong upfront warning that files may be removed without per-item confirmation once they are classified as safe. Users may not understand that generic temp/demo/test heuristics can sweep in files they still care about, particularly when tracking is automatic and persistent across interruptions.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

Including sudo apt remove -y <package> as a standard cleanup action normalizes privileged command execution for a skill driven by conversational triggers. If invoked unintentionally or with a wrong package name, it can remove important system packages and escalate the severity from user-scope cleanup mistakes to system-level damage.

Content

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

md
- winget: `winget uninstall --id <id>` via `execute_command`
- choco: `choco uninstall <package> -y` via `execute_command`
- brew: `brew uninstall <formula>` via `execute_command`
- apt: `sudo apt remove -y <package>` via `execute_command`
- scoop: `scoop uninstall <app>` via `execute_command`

For Skills uninstall:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guide includes commands for uninstalling system-wide software via winget, choco, brew, apt, and snap, which goes beyond cleaning up session-generated artifacts. In an agent skill, this materially increases the risk that a model may remove user-installed software unrelated to the session, causing system disruption or data/configuration loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document provides destructive deletion and uninstall commands without a prominent irreversible-impact warning or a required confirmation workflow. In agent contexts, terse command snippets can be copied or executed by automation, making accidental removal of files, packages, skills, or software more likely.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
86% confidence
Finding

The presence of sudo-backed apt removal guidance enables privileged system modification from within a cleanup reference. While not exploit code by itself, it normalizes root-level package removal in a session-cleanup skill, increasing the chance of overbroad or unsafe privileged actions.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 117)May include surrounding context.

Linux — apt

bash
sudo apt remove <package>
sudo apt purge <package>     # also removes config files
sudo apt autoremove          # remove orphaned dependencies

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

The sudo apt purge example is especially risky because it removes packages and associated configuration files with elevated privileges. In a cleanup skill, this exceeds normal temp-file cleanup and can permanently alter the host environment.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 118)May include surrounding context.

bash
sudo apt remove <package>
sudo apt purge <package>     # also removes config files
sudo apt autoremove          # remove orphaned dependencies

# Example

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
84% confidence
Finding

The sudo apt autoremove guidance can remove additional dependencies beyond the immediately named package, creating hard-to-predict system changes. This is dangerous in an agent skill because the model may not fully understand downstream package relationships before suggesting or executing it.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 119)May include surrounding context.

bash
sudo apt remove <package>
sudo apt purge <package>     # also removes config files
sudo apt autoremove          # remove orphaned dependencies

# Example
sudo apt remove nodejs

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
78% confidence
Finding

This line is an example invocation of sudo apt remove rather than new functionality, but it still reinforces privileged package removal in the skill reference. The risk is contextual and stems from encouraging root-level uninstall actions in a cleanup workflow.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 122)May include surrounding context.

sudo apt autoremove # remove orphaned dependencies

Example

sudo apt remove nodejs

text

### Linux — snap

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
83% confidence
Finding

The sudo snap remove command authorizes privileged removal of installed software, again extending beyond ordinary session cleanup. If used incorrectly, it can remove user applications unrelated to the conversation session.

Content

Scanner excerpt · references/cleanup-guide.md (reported line 128)May include surrounding context.

Linux — snap

bash
sudo snap remove <package>

# Example
sudo snap remove code

Static analysis

No suspicious patterns detected.