T09 · Insecure Skill Coding Practices
Warning
- Location
- src/analyzer.ts:25
- Finding
- Indirect Prompt Injection Through Untrusted Token and News Content<![CDATA[ ## Vulnerability Details **File Location**: `src/analyzer.ts:25-42` and `src/analyzer.ts:75` **Vulnerability Type**: Indirect prompt injection caused by treating untrusted content as LLM instructions **Risk Level**: Medium ### Vulnerable Code ```ts const newsText = news.length > 0 ? news.map((n, i) => `[${i + 1}] ${n.title}: ${n.content}`).join('\n') : '뉴스 데이터 없음'; const marketText = market.current_price_usd ? `현재가: $${market.current_price_usd}, 24h 변동: ${market.price_change_24h_pct?.toFixed(2)}%` : '시장 데이터 없음'; const systemPrompt = `크립토 센티먼트 분석 전문가입니다. 주어진 뉴스와 시장 데이터를 분석하여 반드시 아래 JSON 형식으로만 응답하십시오. 순수 JSON만 출력하고 다른 텍스트는 절대 포함하지 마십시오. { "score": 0~100 사이 정수 (0=매우 부정, 50=중립, 100=매우 긍정), "label": "Bullish 또는 Neutral 또는 Bearish", "summary": "센티먼트 판단 근거를 3문장으로 한국어로 설명" }`; const userMessage = `토큰: ${token}\n시장 데이터: ${marketText}\n\n뉴스:\n${newsText}`; ``` The generated summary is subsequently inserted into another prompt: ```ts const userMessage = `토큰: ${token}\n시장 데이터: ${marketText}\n센티먼트: ${sentiment.label} (점수: ${sentiment.score})\n센티먼트 분석: ${sentiment.summary}`; ``` ### Technical Analysis The `token`, news titles, and news contents are untrusted data. News content originates from Tavily search results, while the token value originates from the job payload. These values are concatenated directly into an LLM user message without robust data boundaries or an explicit instruction that embedded commands must be ignored. An attacker can publish search-indexed content containing instructions such as requests to disregard the system prompt, emit attacker-selected JSON, or manipulate sentiment scores. If Tavily returns that content for a token-related query, it becomes part of the model prompt. The risk is amplified because the free-form `summary` produced by the first model invocation is passed into a second invocation. Instructions retained in that summary can therefore influence both sentiment analysis and final report generation. ...[truncated 1408 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate the token before prompt construction: - Require a string. - Enforce a conservative length limit. - Permit only expected token-name or symbol characters. 2. Enclose external content in explicit structured boundaries, such as JSON fields or clearly marked data blocks. 3. Add a system-level rule stating that token values and retrieved articles are untrusted data and that instructions contained within them must never be followed. 4. Prefer provider-supported structured output or JSON-schema response enforcement instead of relying only on textual instructions. 5. Validate the complete model response: - Require integer scores in the range `0–100`. - Enforce enumerated labels. - Impose strict summary and report length limits. - Reject unexpected properties or types. 6. Do not pass unrestricted free-form model output into a subsequent prompt. Pass only validated structured values, or label the summary explicitly as untrusted model-generated data. 7. Consider preprocessing retrieved articles to remove instruction-like content and limiting input to the factual excerpts required for sentiment analysis. ]]>
