T09 · Insecure Skill Coding Practices
Error
- Location
- multi_source_estimator.py:738
- Finding
- Untrusted Internet Content Can Influence Automated Financial Trades Through Prompt Injection<![CDATA[ ## Vulnerability Details **File Location**: `multi_source_estimator.py:738-791`, `multi_source_estimator.py:926-955`, `multi_source_estimator.py:1017-1062` **Vulnerability Type**: Indirect prompt injection through untrusted external data **Risk Level**: High ### Vulnerable Code ```python def fetch_context(question: str, category: str = "", market_price: float = 0.5, max_chars: int = 2000) -> str: """ Gather real-time context from all relevant sources in parallel. Returns a formatted string (max ~2000 chars) for injection into the LLM prompt. """ categories = detect_categories(question) if category and category not in categories: categories.insert(0, category) parts = [] # Always fetch news news = _match_news(question) if news: parts.append("RECENT NEWS:\n" + "\n".join(news)) # Dispatch category-specific sources in parallel with ThreadPoolExecutor(max_workers=4) as pool: futures = {} if any(c in categories for c in ["economics", "crypto"]): futures[pool.submit(_get_fred_context, question)] = "FRED" if "geopolitics" in categories: futures[pool.submit(_get_gdelt_context, question)] = "GDELT" if "sports" in categories: futures[pool.submit(_get_odds_context, question)] = "ODDS" if "politics" in categories: futures[pool.submit(_get_538_context, question)] = "538" futures[pool.submit(_get_congress_context, question)] = "CONGRESS" if "pharma" in categories: futures[pool.submit(_get_fda_context, question)] = "FDA" if "weather" in categories: futures[pool.submit(_get_meteo_context, question)] = "METEO" if any(kw in question.lower() for kw in ["earthquake", "quake", "seismic"]): futures[pool.submit(_get_usgs_context, question)] = "USGS" if any(kw in question.lower() for kw in ["earnings", "ipo", "revenue", "stock ...[truncated 5061 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat every value obtained from an external feed or API as untrusted data. 2. Place external evidence in a clearly delimited structure and explicitly instruct the model that text inside it is quoted evidence, not executable instructions. 3. Prefer structured, allowlisted fields over arbitrary free-form text. 4. Reject or neutralize context containing instruction-like phrases, role markers, tool requests, JSON-output directives, or attempts to override prior instructions. 5. Preserve source identity and require corroboration from multiple independent sources before external content can materially change a trading estimate. 6. Apply deterministic bounds to how far an LLM estimate may move based on a single source. 7. Validate the model output against independent risk rules rather than relying only on JSON parsing and a divergence threshold. 8. Require manual approval, or a separate deterministic policy decision, before executing live trades based on untrusted textual context. 9. Add adversarial tests containing prompt-injection payloads in RSS titles and API fields. 10. Consider running the LLM analysis and financial execution as separate trust domains, with the execution component accepting only narrowly validated numeric signals. ]]>
