T01 · Skill Instruction Hijacking
Warning
- Location
- scripts/context_gatekeeper.py:41
- Finding
- Untrusted Conversation Content Is Reintroduced as Active Model Context<![CDATA[ ## Vulnerability Details **File Location**: `scripts/context_gatekeeper.py:41-49`, `scripts/context_gatekeeper.py:67-99`, and `SKILL.md:21-23` **Vulnerability Type**: Cross-turn prompt injection through unsanitized context generation **Risk Level**: Medium ### Vulnerable Code ```python def collect_summary(entries: list[dict], limit: int) -> list[str]: sentences = [] for entry in entries: sentences.extend(split_sentences(entry["text"])) if not sentences: return [] if limit <= 0: return [] if len(sentences) <= limit: return sentences half = limit // 2 first_chunk = sentences[:half] last_chunk = sentences[-(limit - half) :] return first_chunk + last_chunk ``` ```python def format_recent(entries: list[dict], count: int) -> list[str]: recent = entries[-count:] if count > 0 else [] formatted = [f"{entry['role']}: {entry['text']}" for entry in recent] return formatted def build_markdown(summary: list[str], pendings: list[str], recent: list[str]) -> str: catalyst = datetime.now(timezone.utc).isoformat(timespec="seconds") sections = ["# Context Gatekeeper", f"_Gerado: {catalyst}_", ""] if summary: sections.append("## Resumo compacto") sections.extend(f"- {sent}" for sent in summary) sections.append("") else: sections.append("## Resumo compacto") sections.append("- Sem conteúdo suficiente para resumir.") sections.append("") if pendings: sections.append("## Pendências e próximos passos") sections.extend(f"- {task}" for task in pendings) sections.append("") else: sections.append("## Pendências e próximos passos") sections.append("- Nenhuma pendência identificada no histórico recente.") sections.append("") if recent: sections.append("## Últimos turnos") sections.extend(f"- {line}" for line in recent) else: sections.append("## Últi ...[truncated 3296 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat all generated conversation summaries as untrusted data and place them inside an explicit, strongly delimited container. 2. Add a trusted instruction outside that container stating that content inside it is historical data only and that commands, policy changes, tool requests, or safety overrides found there must not be followed. 3. Preserve provenance for every retained item, including the original role and turn identifier. Never promote a user-authored statement into an unlabeled summary bullet. 4. Do not inject the summary into a system or developer instruction. Supply it through the least-privileged context channel supported by the host. 5. Replace verbatim extraction with a trusted summarization step that converts messages into factual descriptions and excludes imperative instructions. Pattern filtering may be used as defense in depth but should not be the sole control. 6. Where verbatim recent turns are necessary, encode them as structured data and clearly mark each value as quoted content. 7. Apply tool authorization independently of model output. Require allowlists, argument validation, least-privilege credentials, and confirmation for sensitive reads, writes, network operations, or command execution. 8. Add adversarial tests containing instructions to ignore prior rules, access secrets, invoke tools, or redefine roles. Verify that generated summaries preserve those strings only as inert quotations and that consuming agents do not execute them. 9. Limit retention and protect `context/history.txt` and `context/current-summary.md` with restrictive filesystem permissions because they may contain private conversation data. ]]>
