Back to skill

Security audit

Text Based - Todo List Agent Manager

Security checks for vulnerabilities and agentic risk

Overview

This todo-list skill is mostly purpose-aligned, but its code does not match its storage-boundary and REVIEW-command claims.

Review before installing. The skill does not show malicious behavior, network access, credential access, or shell execution, but its storage path should be fixed or clearly documented because task data may be written to a sibling claw-todolist folder rather than the installed skill folder. The advertised REVIEW feature should also be implemented or removed from the docs.

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
index.js:5
Finding
State File Path Escapes the Skill Directory## Vulnerability Details **File Location**: `index.js`, lines 5-8 and 31-33 **Vulnerability Type**: Filesystem boundary violation caused by an incorrect state directory **Risk Level**: Medium ### Vulnerable Code ```js const SKILL_DIR = path.join(__dirname, '..', 'claw-todolist'); const STATE_FILE = path.join(SKILL_DIR, 'task_state.json'); const RULES_FILE = path.join(SKILL_DIR, 'todo-rules-v3.2.md'); const DISPLAY_CONFIG_FILE = path.join(SKILL_DIR, 'display_config.json'); ``` ```js function saveState(state) { fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2)); } ``` ### Technical Analysis `__dirname` already identifies the directory containing `index.js`. The expression `path.join(__dirname, '..', 'claw-todolist')` first moves to the parent directory and then selects a sibling directory named `claw-todolist`. As a result, the application reads and writes state using: ```text <parent-of-current-skill>/claw-todolist/task_state.json ``` rather than: ```text <current-skill>/task_state.json ``` This behavior contradicts the persistence boundary declared in `SKILL.md`, which states that persistence is confined to the Skill directory. The path is fixed rather than directly user-controlled, so the evidence does not establish an arbitrary-file-write vulnerability. Nevertheless, it permits the Skill to modify a file outside its own installation directory when a matching sibling directory exists. The same incorrect base directory is used for the rules and display configuration files. This can cause the application to consume configuration from a different installation or to silently use fallback values when the sibling files do not exist. ### Attack Path 1. The Skill is installed in a directory whose name or location differs from the hardcoded sibling path. 2. A directory named `claw-todolist` exists under the current Skill directory's parent, potentially belonging to another installatio ...[truncated 1422 chars]
Remediation
## Remediation Suggestions 1. Use the actual module directory as the Skill directory: ```js const SKILL_DIR = __dirname; const STATE_FILE = path.join(SKILL_DIR, 'task_state.json'); const RULES_FILE = path.join(SKILL_DIR, 'todo-rules-v3.2.md'); const DISPLAY_CONFIG_FILE = path.join(SKILL_DIR, 'display_config.json'); ``` 2. Before filesystem access, resolve and verify that every path remains beneath the approved base directory: ```js const SKILL_DIR = path.resolve(__dirname); function resolveWithinSkill(fileName) { const resolved = path.resolve(SKILL_DIR, fileName); if ( resolved !== SKILL_DIR && !resolved.startsWith(SKILL_DIR + path.sep) ) { throw new Error('Resolved path escapes the Skill directory'); } return resolved; } const STATE_FILE = resolveWithinSkill('task_state.json'); ``` 3. If installed package directories are intended to be read-only, store mutable state in an explicitly approved per-user application data directory rather than beside the source code. Keep rules and display configuration read-only inside the package. 4. Use atomic state updates by writing to a securely created temporary file in the same approved directory and then renaming it over the state file. This reduces corruption from interrupted writes. 5. Add tests that install or execute the Skill under arbitrary directory names and assert that all read and write targets remain within the configured storage boundary. 6. Fail closed when path validation fails, and log the resolved destination without exposing task contents.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill metadata and documentation claim that persistence is confined to the skill directory and that a REVIEW command exists, but the analyzed behavior indicates writes occur outside that boundary and the advertised REVIEW behavior is not actually implemented. Misrepresenting storage boundaries can cause unintended file creation or overwrite in adjacent locations, and the mismatch increases the chance that users or agents will trust the skill with stronger isolation guarantees than it actually provides.

Vague Triggers

Medium
Confidence
91% confidence
Finding
This plain-text file contains many generic action phrases such as 'Create', 'Pay', 'Request', 'buy', and 'setup' without any explicit trigger syntax, scope constraints, or negative examples. If this file is used to drive skill invocation or task import, these broad phrases could overlap with ordinary language and cause unintended activation or parsing.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The skill persists task data to task_state.json via fs.writeFileSync, which is a file write affecting user data. While the code performs the write directly, there is no surrounding comment, docstring, or explicit user-facing disclosure at the write site that the skill stores task contents on disk.

Static analysis

No suspicious patterns detected.