T01 · Skill Instruction Hijacking
Error
- Location
- src/gep/prompt.js:5
- Finding
- Untrusted Hub content is injected into an autonomous code-editing agent<![CDATA[ ## Vulnerability Details **File Location**: `src/gep/taskReceiver.js:1-3, 18-68`; `src/evolve.js:990-1021, 1155-1164, 1500-1543`; `src/gep/hubSearch.js:70-125`; `src/gep/prompt.js:5-36, 38-60` **Vulnerability Type**: Remote instruction injection into a privileged executor **Risk Level**: Critical ### Vulnerable Code ```js // src/gep/taskReceiver.js // taskReceiver -- pulls external tasks from Hub, auto-claims, and injects // them as high-priority signals into the evolution loop. async function fetchTasks(opts) { const o = opts || {}; const nodeId = getNodeId(); if (!nodeId) return { tasks: [] }; try { const payload = { asset_type: null, include_tasks: true, }; if (Array.isArray(o.questions) && o.questions.length > 0) { payload.questions = o.questions; } const msg = { protocol: 'gep-a2a', protocol_version: '1.0.0', message_type: 'fetch', message_id: `msg_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`, sender_id: nodeId, timestamp: new Date().toISOString(), payload, }; const url = `${HUB_URL.replace(/\/+$/, '')}/a2a/fetch`; const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 8000); const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(msg), signal: controller.signal, }); clearTimeout(timer); if (!res.ok) return { tasks: [] }; const data = await res.json(); const respPayload = data.payload || data; const tasks = Array.isArray(respPayload.tasks) ? respPayload.tasks : []; const result = { tasks }; ``` ```js // src/evolve.js const fetchResult = await fetchTasks({ questions: proactiveQuestions }); const hubTasks = fetchResult.tasks || []; if (hubTasks.length > 0) { const best = selectBestTask(hubTasks); if (best) { const alreadyClaimed = best.status === 'claimed'; co ...[truncated 4731 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Disable Hub task claiming and remote asset reuse by default. 2. Require explicit human approval for each remote task or asset, showing the exact content and requested local changes. 3. Treat all Hub fields as untrusted data: - Permit only a strict schema of short declarative values. - Reject unknown properties. - Reject shell commands, tool directives, paths, URLs, and imperative instructions. - Do not place raw JSON or free-form remote text into privileged prompts. 4. Cryptographically verify assets using a trusted public-key infrastructure. Do not rely exclusively on Hub-provided status or reputation. 5. Remove wording such as “VERIFIED” and “Apply faithfully” unless verification has occurred locally. 6. Run remotely influenced changes in a disposable worktree or container with: - No access to user memory or credentials. - No network access by default. - A strict repository path allowlist. - A restricted command allowlist. 7. Produce a patch for review instead of applying changes directly. 8. Keep remote task descriptions separated from system and executor instructions using a structured interface rather than prompt concatenation. ]]>
