T01 · Skill Instruction Hijacking
Warning
- Location
- extract.mjs:104
- Finding
- Untrusted Web Content Is Exposed to the Agent Without Safety Boundaries## Vulnerability Details **File Location**: `extract.mjs:104-123, 137-142`; `search.mjs:120-171, 286-305` **Vulnerability Type**: Untrusted-content prompt injection **Risk Level**: Medium ### Vulnerable Code `extract.mjs:104-123`: ```js const text = await response.text(); if (!text || !text.trim()) { return 'Error: no result found'; } // Try to parse as JSON and extract reader_result try { const jsonData = JSON.parse(text); if (jsonData.reader_result) { return jsonData.reader_result; } else if (jsonData.content) { return 'Error: fetch API return wrong format'; } } catch { // Not JSON, return as-is } return text; ``` `extract.mjs:137-142`: ```js if (content.startsWith('Error:')) { console.error(`Error: ${content}`); process.exit(1); } console.log(formatContent(content, url)); ``` `search.mjs:120-137`: ```js // Process organic results if (results.organic) { for (const result of results.organic) { const cleanResult = { type: 'page' }; if (result.title) cleanResult.title = result.title; if (result.desc) cleanResult.desc = result.desc; if (result.url) cleanResult.url = result.url; const url = cleanResult.url; if (url && !seenUrls.has(url)) { seenUrls.add(url); cleanResults.push(cleanResult); } } } ``` `search.mjs:286-305`: ```js if (isImageSearch) { results = await performImageSearch(query, site, days > 0 ? days : -1, imageSize); console.log(JSON.stringify({ query: query, total_results: results.length, results: results, usage_hint: "Use the 'image_url' values as reference images in image generation. Download them first if needed." }, null, 2)); } else { results = await performWebSearch(query, site, days > 0 ? days : -1); console.log(JSON.stringify({ query, search_type: searchType, count: results.length, results }, ...[truncated 2127 chars]
- Remediation
- ## Remediation Suggestions 1. Wrap all search and extraction output in a structured envelope that explicitly labels it as untrusted external data. 2. Add a warning for the consuming agent stating that commands, policies, credentials requests, or tool-use instructions found in returned content must not be followed. 3. Prefer a strict JSON schema with separate fields for metadata and content rather than emitting free-form page bodies. 4. Remove active HTML elements and non-content material, including scripts, styles, hidden text, and embedded metadata not required for extraction. 5. Apply prompt-injection detection or flagging before returning content. Detection should supplement rather than replace isolation because filters can be bypassed. 6. Ensure the calling agent treats Skill output as data with lower precedence than system, developer, and user instructions. 7. Require confirmation before any subsequent privileged action is based solely on instructions found in retrieved content.
