T01 · Skill Instruction Hijacking
Warning
- Location
- scripts/taskboard.py:302
- Finding
- Stored Hook Instructions Can Hijack Agent Tool Actions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/taskboard.py:260-269, 302-305`; related trust guidance in `SKILL.md:78` **Vulnerability Type**: Stored instruction injection through unvalidated task hooks **Risk Level**: Medium ### Vulnerable Code ```python if getattr(args, "on_ack", None) is not None: old = task["on_ack"] if "on_ack" in task.keys() else None changes.append(("on_ack", old, args.on_ack)) updates.append("on_ack = ?") params.append(args.on_ack) if getattr(args, "on_done", None) is not None: old = task["on_done"] if "on_done" in task.keys() else None changes.append(("on_done", old, args.on_done)) updates.append("on_done = ?") params.append(args.on_done) ``` ```python # Refresh and emit hooks task = db.execute("SELECT * FROM tasks WHERE id = ?", (args.id,)).fetchone() if args.status == "in_progress" and task["on_ack"]: print(f"\n🔔 ON_ACK: {task['on_ack']}") if args.status == "done" and task["on_done"]: print(f"\n🔔 ON_DONE: {task['on_done']}") ``` The associated operational guidance states: ```text The agent reads these lines and decides how to act (send a message, spawn a session, create a task, etc.). ``` ### Technical Analysis The `--on-ack` and `--on-done` arguments accept unrestricted text. That text is persisted in SQLite and later printed using a trusted-looking `ON_ACK` or `ON_DONE` marker. No parser, action allowlist, destination validation, authorization check, or separation between data and instructions is applied before emission. Parameterized SQL prevents SQL injection, but it does not address instruction injection. The security boundary is crossed when an AI agent or wrapper interprets the emitted value as an instruction and invokes privileged messaging, session, or task-management tools. Because the value is stored, the malicious instruction may execute later when another operator changes the task status. The Python CLI itself does not execute the hook as shell code and ...[truncated 1599 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace free-form hook strings with a structured schema containing explicit fields such as `action`, `destination`, and `message`. 2. Allowlist supported action types and reject unknown actions rather than passing them to an agent for interpretation. 3. Validate destination identifiers against an administrator-controlled allowlist. 4. Treat message bodies as inert content and explicitly prohibit consumers from interpreting them as secondary instructions. 5. Require explicit user confirmation before external messaging, session creation, or any other consequential tool invocation. 6. Record the hook creator and enforce authorization checks when hooks are created, modified, and triggered. 7. Escape or encode control characters and multiline content before emitting machine-readable output. 8. Prefer a versioned JSON event format over trusted-looking natural-language instructions, for example: ```json { "event": "task_done", "task_id": 5, "action": "notify", "destination": "approved-channel-id", "message": "Task completed" } ``` 9. Document that hook fields are untrusted data and that integrations must independently validate every requested action. 10. If automation is required, run the consumer with narrowly scoped tool permissions and deny session creation or arbitrary destinations by default. ]]>
