Back to skill

Security audit

Todo Accelerator

Security checks for vulnerabilities and agentic risk

Overview

This task-board automation skill is coherent, but it needs review because editable task names and notes can drive automatic agent work and can reach Markdown files outside the intended notes folder.

Review before installing if your workspace has shared or externally edited task boards. Use it only with trusted task inputs, choose a confined notes folder, avoid task names containing path characters, disable automatic heartbeat pickup unless you want unattended task execution, and prefer installing PyYAML in a pinned virtual environment.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T01 · Skill Instruction Hijacking

Error
Location
scripts/todo.py:429
Finding
Persistent Agent Instruction Hijacking Through Untrusted Task Content## Vulnerability Details **File Location**: `scripts/todo.py:429-489`, `references/processing-work-on-todo.md:3-13`, `initialization.md:60-65` **Vulnerability Type**: Stored prompt injection through task metadata and note content **Risk Level**: High ### Vulnerable Code `scripts/todo.py:429-489`: ```python # ── Build output (data fields only; instructions are in SKILL.md) ── target_lines = _real_lines(sections.get("Target", "")) inv_heading = get_investigation_heading(sections) inv_lines = _real_lines( sections.get(inv_heading, "") ) if inv_heading else [] out: list[str] = [] out.append(f"## Working on: {selected['name']}") out.append(f"Note: {note_path}") out.append(f"Iteration: {new_iterate}") out.append("") targets = fm.get("target") or [] if isinstance(targets, str): targets = [targets] if targets: out.append("### Expected Results") for t in targets: out.append(f"- {t}") out.append("") out.append("### Unresolved Issues") for item in unchecked: out.append(f"- [ ] {item}") out.append("") if target_lines: out.append("### Previous Results") for ln in target_lines: out.append(ln) out.append("") inv_name = inv_heading or "Investigation and Problems" if inv_lines: out.append( f"Previous findings are in the \"{inv_name}\" section of the note. " "Review before starting; record any new discoveries in the same section. " "Keep entries concise — facts and conclusions only, no filler." ) out.append("") assigned_agent = fm.get("assigned-agent") if assigned_agent: out.insert(0, ( f"⚠️ DELEGATION REQUIRED: This to-do is assigned to agent " f"\"{assigned_agent}\". Notify agent \"{assigned_agent}\" and " f"pass the task details below to it. The agent must follow the " f"todo-accelerator skill workflow to process this to-do." )) out.inser ...[truncated 3977 chars]
Remediation
## Remediation Suggestions 1. Treat every task field and note section as untrusted data, including values that were previously produced by an Agent. 2. Place untrusted values inside clearly delimited data blocks and explicitly instruct the Agent never to interpret content inside those blocks as commands, policy, delegation instructions, or tool-call authorization. 3. Use a structured serialization format such as JSON with fixed fields instead of generating an instruction-style Markdown prompt. 4. Validate `assigned-agent` against an administrator-controlled allowlist of known agent identifiers. Do not generate `DELEGATION REQUIRED` from an arbitrary note value. 5. Require explicit user confirmation before delegation, external communication, execution, sensitive file access, or other consequential actions requested by task content. 6. Apply prompt-injection screening to requirements, targets, and note sections. Suspicious content should be displayed for review rather than automatically processed. 7. Avoid unconditional heartbeat processing of untrusted tasks. Heartbeats should identify a candidate task and request approval before acting when the task source is not trusted. 8. Record provenance for each task and enforce stricter handling for externally supplied or collaboratively edited notes.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/todo.py:385
Finding
Filesystem Path Traversal Through Unsanitized Task Names## Vulnerability Details **File Location**: `scripts/todo.py:333-340`, `scripts/todo.py:385-389`, `scripts/todo.py:506-510`, `scripts/todo.py:580-584` **Vulnerability Type**: Path traversal and unrestricted Markdown file access **Risk Level**: High ### Vulnerable Code `scripts/todo.py:333-340`: ```python board_path = config["board"] notes_dir = config["notes_folder"] tmpl_path = config["template"] name = args.name if not board_path.exists(): print(f"Error: board not found: {board_path}", file=sys.stderr) sys.exit(1) ``` `scripts/todo.py:385-389`: ```python # Write companion note notes_dir.mkdir(parents=True, exist_ok=True) note_path = notes_dir / f"{name}.md" if note_path.exists(): print(f"Note already exists: {note_path} (skipped)") else: note_path.write_text(content, encoding="utf-8") ``` `scripts/todo.py:506-510`: ```python note_path = selected["note_path"] if not note_path.exists(): print(f"Error: note not found: {note_path}", file=sys.stderr) sys.exit(1) fm, sections = parse_note(note_path) ``` `scripts/todo.py:580-584`: ```python name = args.name completed = args.completed or [] note_path = notes_dir / f"{name}.md" if not note_path.exists(): ``` Similar unchecked path construction also occurs when candidate and pending-note paths are derived from board card names: ```python note_path = notes_dir / f"{card['name']}.md" ``` ### Technical Analysis A task name is used directly as part of a filesystem path. The code does not reject path separators, traversal components such as `..`, absolute paths, control characters, or platform-specific path syntax. It also does not resolve the resulting path and verify that it remains inside the configured notes directory. With a value such as `../../HEARTBEAT`, the expression below can refer to a file outside `notes_dir`: ```python notes_dir / "../../HEARTBEAT.md" ``` The `add-todo` ...[truncated 2104 chars]
Remediation
## Remediation Suggestions 1. Reject task names containing `/`, `\`, `..`, absolute-path syntax, NUL bytes, control characters, or platform-specific reserved filename characters. 2. Convert display names to safe, generated filenames rather than using names directly. A random identifier or validated slug should be stored separately from the human-readable title. 3. Resolve every destination before access and enforce containment: ```python candidate = (notes_dir / f"{safe_name}.md").resolve() notes_root = notes_dir.resolve() if not candidate.is_relative_to(notes_root): raise ValueError("Task note path escapes the notes directory") ``` 4. Apply the containment check before every note read, write, update, and existence check, including paths derived from board cards. 5. Validate existing board card names before processing them because a board can be edited independently of `add-todo`. 6. Consider opening new notes with exclusive creation semantics to prevent race conditions and unintended replacement. 7. Add regression tests covering `../`, nested traversal, absolute paths, backslash traversal, encoded-looking separators, control characters, and symlink-based escapes. 8. If symlinks are permitted in the notes directory, verify the resolved final target rather than only validating the lexical path.

T08 · Insecure Dependencies

Warning
Location
initialization.md:8
Finding
Unpinned PyYAML Installation in the Active Python Environment## Vulnerability Details **File Location**: `initialization.md:8-11` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```markdown 1. **Python 3** with **PyYAML** installed: ```bash pip3 install PyYAML ``` ``` ### Technical Analysis The initialization instructions install PyYAML without a version constraint, dependency lock file, integrity hash, isolated virtual environment, or explicitly trusted package index. The installed artifact is therefore determined by package-index state at setup time. This is not evidence that PyYAML itself is malicious. The weakness is that builds are not reproducible and setup implicitly trusts whichever matching release and transitive installation artifacts are returned by the configured Python package index. Future package compromise, index misconfiguration, or an incompatible release could consequently affect the skill. Because the command uses `pip3` directly, it may also alter a shared or system-associated Python environment instead of a project-specific environment. ### Attack Path 1. An operator follows the documented prerequisite command. 2. `pip3` queries its configured package index for the current PyYAML release because no version or hash is specified. 3. A compromised index account, unsafe mirror, index configuration, or future malicious release supplies an unexpected artifact. 4. The artifact is installed into the active Python environment. 5. The dependency's code executes when `scripts/todo.py` imports `yaml`, with the privileges of the Agent process. ### Impact Assessment A compromised dependency would execute with the same filesystem, network, and process privileges as the Python interpreter running the skill. This could affect all data accessible to that Agent environment. Even without malicious compromise, unconstrained upgrades can introduce incompatible parsing or serialization behavior and ...[truncated 35 chars]
Remediation
## Remediation Suggestions 1. Pin PyYAML to a reviewed version in a requirements or lock file. 2. Include cryptographic hashes and install with hash verification, for example through `pip install --require-hashes -r requirements.txt`. 3. Use a dedicated virtual environment rather than installing into the active global Python environment. 4. Document and enforce the trusted package index instead of relying on arbitrary local pip configuration. 5. Add automated dependency scanning and a controlled process for reviewing and updating pinned versions. 6. Record the supported Python and PyYAML versions so deployments remain reproducible.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill directs the agent to invoke a Python script and to write/update companion markdown notes, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization ambiguity where a host agent may grant broader file read/write access than users expect, increasing the chance of unintended workspace modification during routine task handling.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The activation description is very broad and includes common situations like user interest in a topic, heartbeat events, bookmarks, and help preparing deliverables. This can cause the skill to trigger without clear user intent, leading the agent to create, modify, or advance todos and associated files unexpectedly.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The initialization instructions direct the agent to run a command that creates a notes folder, copies a board template, and writes a configuration file to user-specified paths, but they do not explicitly require warning the user that files will be created or overwritten in those locations. In an agent context, this can lead to unintended filesystem modifications if the user does not fully understand the side effects or if ambiguous paths are provided.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The template requirements mandate specific non-English headings, including Chinese labels '推进中' and '审阅中', with no indication that the user can choose or opt into that locale. This is a natural-language locale constraint that appears undocumented and not justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code injects Chinese default target text ("你期待的结果1", "你期待的结果2") when the user does not provide targets, which imposes a language choice without opt-in. That violates the language/locale policy because the skill does not offer a user language selection or document a justified locale constraint.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The skill moves items to headings named "审阅中" and "推进中" and prints those labels to the user as part of normal operation. Because the file does not offer a language choice or explain that the tool is intentionally Chinese-localized, this is a natural-language locale policy violation.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The instructions hard-code workflow states using Chinese labels like '审阅中' and '推进中' without indicating that the user can choose the language or that the skill is region-specific. This creates a locale policy concern because the skill imposes a specific language in its natural-language workflow labels without documented user opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The template includes Chinese headings such as "推进中" and "审阅中" while other headings are in English. This creates a language/locale constraint in the skill artifact without any explanation, opt-in, or indication that the template is intended for a Chinese-speaking context.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The markdown includes the status label "推进中" as part of the skill workflow, which imposes a non-English locale in user-facing behavior. The file does not indicate that this locale is optional, configurable, or required for a region-specific purpose.

Natural-Language Policy Violations

Low
Confidence
98% confidence
Finding
The output example moves the to-do to "审阅中", a Chinese-language state name, but the skill description does not explain or make this locale behavior optional. This can violate language/locale policy when users are not given an explicit choice.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The final case study again shows the skill moving items to "审阅中" with no accompanying language-selection mechanism or justification. Repeated default use of a fixed locale in user-visible outputs suggests a natural-language policy issue.

Static analysis

No suspicious patterns detected.