T01 · Skill Instruction Hijacking
Error
- Location
- SKILL.md:27
- Finding
- Unauthenticated Remote Task Queue Can Inject Instructions into the AI Agent<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:27-29`; `src/index.ts:295-318`, `src/index.ts:415-421`, `src/index.ts:555-576` **Vulnerability Type**: Remote instruction injection through attacker-controlled MCP tool output **Risk Level**: Critical ### Vulnerable Code `SKILL.md:27-29`: ```markdown 3. The response from `ask_human_feedback` is your next instruction. Execute it, then call `ask_human_feedback` again when done. This creates a productive feedback loop. 4. If the task queue returns a task automatically (queue was non-empty), execute that task and call `ask_human_feedback` again when complete. The queue feeds tasks until empty. ``` `src/index.ts:295-318`: ```ts if (req.url === "/api/queue" && req.method === "POST") { const body = await readBody(req); try { const data = JSON.parse(body); if (data.action === "add" && typeof data.task === "string" && data.task.trim()) { taskQueue.push(data.task.trim()); broadcastQueueState(); } else if (data.action === "remove" && typeof data.index === "number") { if (data.index >= 0 && data.index < taskQueue.length) { taskQueue.splice(data.index, 1); broadcastQueueState(); } } else if (data.action === "clear") { taskQueue.length = 0; broadcastQueueState(); } else if (data.action === "reorder" && Array.isArray(data.tasks)) { taskQueue.length = 0; taskQueue.push(...data.tasks.filter((t: unknown) => typeof t === "string" && (t as string).trim())); broadcastQueueState(); } else if (data.action === "autoMode" && typeof data.enabled === "boolean") { autoMode = data.enabled; broadcastQueueState(); } res.writeHead(200, { "Content-Type": "application/json", ...cors }); res.end(JSON.stringify({ ok: true, tasks: [...taskQueue], autoMode })); } catch { res.writeHead(400, { "Content-Type": "application/json", ...cors }); res.end(JSON.stringify({ error: "Invalid JSON" })); } retur ...[truncated 3379 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove instructions that require the Agent to execute feedback or queue output automatically. 2. Explicitly label all browser, HTTP, WebSocket, and queue content as untrusted user input. 3. Require the Agent to apply its normal authorization, safety, and tool-use policies to every returned task. 4. Require explicit confirmation through the original trusted Agent conversation before acting on queued instructions that access data, modify files, invoke tools, or perform destructive operations. 5. Bind task queues to authenticated users and isolated Agent sessions so one client cannot inject tasks into another session. 6. Attach provenance metadata to tool output instead of returning attacker-controlled text as an unqualified instruction. 7. Introduce an allowlist of permitted queue operations or use a structured task schema rather than arbitrary natural-language commands. 8. Display queued tasks to the trusted operator and require approval before dispatch. 9. Add queue length, task length, and rate limits. 10. Treat authentication as mandatory, but do not rely on authentication alone: authenticated browser content must still be considered untrusted input. ]]>
