T09 · Insecure Skill Coding Practices
- Location
engine.py:187- Finding
Indirect Prompt Injection Through Untrusted Competitor Content
- Content
View full analysis
{ const results = []; // Organic results document.querySelectorAll('#search .g, #rso .g').forEach(el => { const titleEl = el.querySelector('h3'); const linkEl = el.querySelector('a[href^="http"]'); const snippetEl = el.querySelector('[data-sncf], .VwiC3b, [style*="-webkit-line-clamp"]'); if (titleEl && linkEl) { results.push({ title: titleEl.textContent.trim(), url: linkEl.getAttribute('href'), snippet: snippetEl ? snippetEl.textContent.trim() : '' }); } }); return results.slice(0, 10); }""") ``` Headings are also collected from arbitrary competitor pages: ```python data = await page.evaluate("""() => { const headings = []; document.querySelectorAll('h1, h2, h3').forEach(h => { headings.push({ level: h.tagName.toLowerCase(), text: h.textContent.trim().substring(0, 200) }); }); // Estimate word count const article = document.querySelector('article, main, [role="main"], .post-content, .entry-content'); const text = (article || document.body).innerText; const wordCount = text.split(/\\s+/).length; return {headings, word_count: wordCount}; }""") ``` The resulting attacker-controlled text is directly interpolated into the generation prompt: ```python serp_section = "" if serp_results: serp_section = "## Top Competing Articles\n" for i, r in enumerate(serp_results[:10], 1): serp_section += f"{i}. ...[truncated 3428 chars]- Remediation
View remediation
