T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:223
- Finding
- Untrusted Remote Thread Content Can Manipulate LLM-Generated Public Comments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:223-246`, `SKILL.md:269-275`, and `references/analysis-pattern.md:13-18` **Vulnerability Type**: Prompt injection through untrusted remote content followed by an external side effect **Risk Level**: High ### Vulnerable Code Snippets From `SKILL.md:223-246`: ```markdown Use `thread.text` as the main input for analysis; optionally include `price_on_fetch` and `citations` in the prompt. --- ## Analyze thread and produce conviction 1. **Inputs:** `thread.text` (required), optionally `thread.price_on_fetch`, `thread.citations`, `thread.id`, `thread.project_id`. 2. **Output:** Structured object: - `summary` — short analysis text (e.g. 20–300 chars), in the agent's voice. - `conviction` — number: predicted **percent price change over 3 hours**, one decimal (e.g. `2.6` = +2.6%, `-3.5` = -3.5%, `0` = neutral). 3. **Optional:** `skip` (boolean). If `true`, do not post a comment (e.g. outside expertise or no strong take). Use your LLM with structured output (e.g. zod schema + Vercel AI SDK `Output.object`, or equivalent) so the model returns `{ summary, conviction }` or `{ skip, summary?, conviction? }`. Do not post when `skip === true` or when analysis fails. ``` From `SKILL.md:269-275`: ```markdown 1. **Load state** from `./hive-{Name}.json`. If no valid `apiKey` → register, then save `apiKey` to the file. 2. **Query threads:** If `cursor` exists, call `GET /thread?limit=20×tamp={cursor.timestamp}&id={cursor.id}` so only **new** threads are returned. Otherwise `GET /thread?limit=20`. 3. For each thread in the response: - If `thread.locked`, skip. - **Analyze** using `thread.text` (and optional context) → get `summary` and `conviction` (or skip). - If not skipping: **Post comment** `POST /comment/:threadId` with `{ text, thread_id, conviction }`. 4. **Save state:** Set `cursor` to the newest thread's `timestamp` and `id` (so next run only fetches newer threads). Persist `apiKey` ...[truncated 2437 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Place remote fields inside explicit data delimiters and state in the trusted system prompt that instructions found inside those delimiters must never be followed. 2. Treat `thread.text`, citation titles, URLs, project identifiers, and all other API response fields as untrusted input. 3. Use a narrowly scoped system prompt that permits only market-signal analysis and explicitly prohibits obeying remote instructions, disclosing context, advertising, or generating operational commands. 4. Add semantic validation after structured generation. Reject summaries containing instruction-like text, unexpected URLs, credential material, unrelated content, or unsupported calls to action. 5. Constrain `conviction` to a documented numeric range and normalize it to one decimal place. 6. Require human approval before posting when the input or output triggers injection heuristics. 7. Log rejection reasons without recording credentials or sensitive prompt context. 8. Include adversarial prompt-injection cases in automated tests and fail closed whenever analysis or validation is uncertain. ]]>
