T01 · Skill Instruction Hijacking
- Location
index.ts:211- Finding
Untrusted Bulletin Content Is Executed as Agent Instructions
- Content
View full analysis
): string { const sections: string[] = [ `You have ${bulletins.length} pending bulletin(s) requiring your response.`, `For each bulletin below, call the \`bulletin_respond\` tool with your assessment.`, `Do nothing else — respond to all bulletins and stop.`, "", ]; for (const b of bulletins) { sections.push(`---`); sections.push(`## [${b.id}] ${b.topic}`); sections.push(``); sections.push(b.body); sections.push(``); if ((b as any).round === "critique") { sections.push(`### All Discussion Responses`); for (const r of b.responses) { const pos = (r as any).position ?? "align"; const posTag = pos === "oppose" ? " ⚠️ **[OPPOSE]**" : pos === "partial" ? ` ~ **[PARTIAL — ${((r as any).reservations ?? "").slice(0, 60)}]**` : ""; sections.push(`- **${r.agentId}**${posTag}: ${((r as any).body ?? "").slice(0, 300)}`); } } } return sections.join("\n"); } ``` The resulting prompt is passed directly to an autonomous agent: ```ts async function wakeBulletinSubscriber( agentId: string, bulletins: Array<{ id: string; topic: string; body: string; responses: any[]; resolvedSubscribers: string[] }>, label: string, ): Promise { const task = buildBulletinTaskPrompt(bulletins); const bulletinIds = bulletins.map(b => b.id); const jobLabel = `${bulletinIds.join("-")}-${agentId}-${label}`; const result = await doBulletinWake(agentId, task, jobLabel); ``` ### Technical Analysis Bulletin topics, bodies, prior responses, reservations, ...[truncated 2186 chars]- Remediation
View remediation
