T01 · Skill Instruction Hijacking
- Location
search_dorks_skill/models.py:88- Finding
Untrusted Search Results Are Inserted Directly into LLM Context
- Content
View full analysis
Vulnerability Details
File Location:
search_dorks_skill/models.py:88-110; untrusted fields originate fromsearch_dorks_skill/client.py:110-129
Vulnerability Type: Indirect prompt injection through external search content
Risk Level: MediumVulnerable Code
python def parse_results(self, raw_response: dict[str, Any]) -> list[SearchResult]: """Convert raw SearXNG JSON response to SearchResult objects.""" results = [] for item in raw_response.get("results", []): results.append(SearchResult( title=item.get("title", ""), url=item.get("url", ""), snippet=item.get("content", ""), engines=item.get("engines", []), score=float(item.get("score", 0.0)), category=item.get("category", "general"), positions=item.get("positions", []), metadata={ "template": item.get("template", ""), "parsed_url": item.get("parsed_url", []), "publishedDate": item.get("publishedDate", ""), "thumbnail": item.get("thumbnail", ""), "img_src": item.get("img_src", ""), }, )) return resultspython def to_context(self, max_results: int = 20) -> str: """Format results for LLM context window.""" lines = [ f"=== Search Report ===", f"Query: {self.query}", f"Intent: {self.intent.category.value}/{self.intent.subcategory}", f"Strategy: {self.strategy.name}", f"Results: {len(self.results)} (of {self.total_found} total)", f"Engines: {', '.join(self.engines_used)}", f"Time: {self.timing_seconds:.2f}s", "", ] for i, r in enumerate(self.results[:max_results], 1): lines.append(f"[{i}] {r.title}") lines.append(f" URL: {r.url}") lines.append(f" {r.snippet[:300]}") ...[truncated 2352 chars]- Remediation
View remediation
Remediation Suggestions
- Prefer returning typed, structured result objects rather than a prompt-ready string.
- When text rendering is required, wrap every external field in explicit untrusted-data delimiters.
- Add a fixed instruction before results stating that titles, URLs, snippets, and suggestions are untrusted evidence and must never be interpreted as commands.
- Remove control characters and escape markup or delimiter sequences that could break the intended result structure.
- Keep external result data in a separate model/tool-response channel where the integration platform supports one.
- Apply prompt-injection detection and either flag or omit snippets containing instruction-like content.
- Require confirmation before a downstream agent performs consequential tool actions based solely on search-result content.
- Document that
to_context()output must not be concatenated into privileged system or developer instructions.
