T01 · Skill Instruction Hijacking
Warning
- Location
- scripts/auto-tweet.js:26
- Finding
- Untrusted X Trend Content Is Passed into the Agent Content-Generation Flow<![CDATA[ ## Vulnerability Details **File Location**: `scripts/auto-tweet.js:26-36`, `scripts/auto-tweet.js:62-65`, `scripts/trends.js:25-36`, `scripts/generate-ideas.js:20-25`, and `scripts/generate-ideas.js:38-42` **Vulnerability Type**: Indirect prompt injection through untrusted external content **Risk Level**: Medium ### Vulnerable Code `scripts/auto-tweet.js:26-36`: ```js const trends = await page.evaluate(() => { const trendElements = document.querySelectorAll('[data-testid="trend"]'); return Array.from(trendElements).slice(0, 10).map(el => { const nameEl = el.querySelector('[dir="ltr"]'); const tweetCountEl = el.querySelector('span:last-child'); return { topic: nameEl ? nameEl.textContent : 'Unknown', tweets: tweetCountEl ? tweetCountEl.textContent : '0' }; }); }); ``` `scripts/auto-tweet.js:62-65`: ```js fs.writeFileSync(trendsFile, JSON.stringify({ timestamp: new Date().toISOString(), trends }, null, 2)); ``` `scripts/trends.js:25-36`: ```js const trends = await page.evaluate(() => { const trendElements = document.querySelectorAll('[data-testid="trend"]'); return Array.from(trendElements).slice(0, 10).map(el => { const nameEl = el.querySelector('[dir="ltr"]'); const tweetCountEl = el.querySelector('span:last-child'); return { topic: nameEl ? nameEl.textContent : 'Unknown', tweets: tweetCountEl ? tweetCountEl.textContent : '0', timestamp: new Date().toISOString() }; }); }); ``` `scripts/generate-ideas.js:20-25`: ```js const data = JSON.parse(fs.readFileSync(trendsFile, 'utf8')); const trends = data.trends; console.log('🔥 Top 5 Trending Topics:'); console.log('========================\n'); trends.slice(0, 5).forEach((trend, i) => { ``` `scripts/generate-ideas.js:38-42`: ```js // Return trends as JSON for agent to process console.log('\n---TRENDS_JSON---'); console.log(JSON.stringify(trends.slice(0, 5), null, 2)); console.log('---END_TRENDS_JSON---'); ``` ...[truncated 2478 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all scraped website values as untrusted data and state this explicitly in every agent prompt that consumes them. 2. Require the agent to ignore commands, policy statements, tool requests, encoded payloads, and role-like instructions found inside trend fields. 3. Pass trends through a structured tool interface with a strict schema instead of incorporating console output directly into an instruction prompt. 4. Validate each field before storage and processing: - Enforce conservative maximum lengths. - Remove control characters and bidirectional text controls. - Reject unexpected multiline values. - Accept only the fields needed for topic analysis. 5. Keep data and instructions in separate prompt sections. For example, state that quoted trend fields are evidence to summarize and can never modify the task. 6. Use a dedicated low-privilege generation step that has no browser-posting or sensitive-context access. 7. Preserve a mandatory, explicit human approval boundary before every post. Approval should display the exact final text that will be submitted. 8. Record the source and processing history of each generated tweet so suspicious trend inputs can be traced. ]]>
