T09 · Insecure Skill Coding Practices
- Location
src/analyzer.ts:38- Finding
Indirect Prompt Injection Through Untrusted News Content
- Content
View full analysis
`[${i + 1}] 제목: ${a.title}\nURL: ${a.url}\n내용: ${a.content.slice(0, 300)}` ).join('\n\n'); const systemPrompt = `당신은 뉴스 요약 전문가입니다. 주어진 뉴스 기사 목록을 분석하여 반드시 아래 JSON 형식으로만 응답하십시오. 다른 텍스트, 설명, 마크다운 코드블록 없이 순수 JSON만 출력하십시오. 응답 형식: [ { "title": "기사 제목", "url": "기사 URL", "summary": "3줄 이내 한국어 요약", "published_date": "날짜 또는 알 수 없음", "importance_score": 1~5 사이 정수 (5가 가장 중요) } ]`; const userMessage = `주제: ${topic}\n\n기사 목록:\n${articlesText}`; try { const raw = await callLLM(systemPrompt, userMessage); const cleaned = raw.replace(/```json|```/g, '').trim(); return JSON.parse(cleaned); } ``` The resulting model-generated summaries are subsequently inserted into another prompt: ```ts const top5 = [...articles].sort((a, b) => b.importance_score - a.importance_score).slice(0, 5); const summaries = top5.map((a, i) => `${i + 1}. ${a.summary}`).join('\n'); const systemPrompt = `당신은 뉴스 브리핑 전문가입니다. 주어진 뉴스 요약들을 바탕으로 5문장 이내의 자연스러운 한국어 브리핑을 작성하십시오. 마크다운 형식으로 작성하되, 헤더(#)는 사용하지 마십시오.`; const userMessage = `주제: ${topic}\n\n주요 뉴스 요약:\n${summaries}`; return await callLLM(systemPrompt, userMessage); ``` ### Technical Analysis Article titles, URLs, and content returned by Tavily are externally controlled web data. The application interpolates these fields directly into an instruction-bearing LLM message without establishing a clear trust boundary or telling the model to treat embedded instructions as untrusted data. An attacker can publish content whose title or first 300 characters contain instructions directed at the model. If Tavily returns that page, the embedded instructions become part of the LLM prompt. Requiring JSON outpu ...[truncated 2549 chars]- Remediation
View remediation
