T01 · Skill Instruction Hijacking
- Location
scripts/evolve/propose_skill_update.py:157- Finding
Untrusted feedback is embedded into persistent Agent-loaded Skill instructions
- Content
View full analysis
Vulnerability Details
File Location:
scripts/evolve/propose_skill_update.py:88-93, 127-153, 157-194, 231-233
Vulnerability Type: Persistent instruction injection through feedback-derived Skill content
Risk Level: HighVulnerable Code
python def explicit_trigger_suggestions(entries: list[dict]) -> list[str]: triggers = [] patterns = [ r"(?:trigger|trigger phrase|触发词|触发语)[::]\s*([^。\n;;]+)", r"(?:when user says|用户说)[::]\s*([^。\n;;]+)", ] for entry in entries: text = "\n".join(str(entry.get(key) or "") for key in ["feedback", "expected", "task"]) for pattern in patterns: for match in re.findall(pattern, text, flags=re.IGNORECASE): value = clean_trigger(match) if value and value not in triggers: triggers.append(value) return triggers[:8]python def add_trigger_cues(skill_md: Path, triggers: list[str]) -> list[str]: if not triggers: return [] content = skill_md.read_text(encoding="utf-8") existing = set(re.findall(r"(?m)^\s*-\s+`?([^`\n]+?)`?\s*$", content)) to_add = [trigger for trigger in triggers if trigger not in existing] if not to_add: return [] insertion = "\n".join(f"- `{trigger}`" for trigger in to_add) if "## Trigger Cues" in content: pattern = re.compile( r"(?ms)(## Trigger Cues.*?Use this skill when the user mentions:\n\n)(.*?)(\n## |\Z)" ) new_content, replacements = pattern.subn( lambda match: match.group(1) + match.group(2).rstrip() + "\n" + insertion + match.group(3), content, count=1, ) if replacements == 0: new_content = content.rstrip() + "\n" + insertion + "\n" content = new_content else: content += "\n\n## Trigger Cues\n\nUse this skill when the user mentions:\n\n" + insertion + "\n" skill_md.write_text(content, encoding="utf-8") ...[truncated 4801 chars]- Remediation
View remediation
Remediation Suggestions
- Do not place raw feedback in files that an Agent may load as instructions.
- Store feedback outside the Skill package in a dedicated data store with a strict separation between instructions and evidence.
- If feedback must accompany a candidate, serialize it as inert JSON and ensure the Agent-facing instructions explicitly prohibit treating its contents as commands.
- Escape Markdown metacharacters and normalize or reject newlines, headings, code blocks, links, role labels, and instruction-like directives.
- Add an instruction-injection scanner covering
SKILL.md, all references, generated Agent metadata, and scripts before validation can pass. - Require explicit human review of each feedback-derived textual change rather than approving only aggregate scores.
- Maintain an allowlist for trigger syntax and reject trigger values containing control language, tool commands, URLs, or role directives.
- Record provenance and trust level for every generated section so untrusted feedback cannot silently become authoritative Skill guidance.
