T02 · Agent Memory Poisoning
- Location
SKILL.md:55- Finding
Persistent Agent Memory Poisoning Through Unvalidated Learning State
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:55-77andscripts/learner.py:69-96
Vulnerability Type: Persistent memory poisoning through automatically reused user-controlled preferences and agent-directed modification of governing instructions
Risk Level: HighVulnerable Code and Instructions
The following is an English translation of the relevant instructions in
SKILL.md:55-77:markdown This skill includes the general learning module `scripts/learner.py`. After each use, it automatically reviews and accumulates experience to improve future output quality and efficiency without manual maintenance. `learned_patterns.json` records operation totals, capability usage frequency, error patterns, user preferences, and improvement suggestions. # Record a failure or exception python scripts/learner.py record <skill-directory> \ --capability capability-name --fail \ --error recognition-failure --note "User supplied a nonstandard file" # Record a user preference for direct use next time python scripts/learner.py prefer <skill-directory> \ --key output-language --val preferred-value Iteration rules: - When an error accumulates at least three occurrences, proactively add validation or fallback steps and write the experience back into this skill's `SKILL.md`. - Important user preferences are written into `learned_patterns.json` and directly adopted the next time the skill is invoked.The persistence implementation in
scripts/learner.py:69-96is:python def save_learning(skill_dir, data): data["lastUpdated"] = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M") p = learn_path(skill_dir) with open(p, "w", encoding="utf-8") as f: f.write(json.dumps(data, indent=2, ensure_ascii=False)) def record_op(skill_dir, capability, success=True, error=None, note=None): data = load_learning(skill_dir) data["totalOps"] += 1 ...[truncated 4435 chars]- Remediation
View remediation
Remediation Suggestions
- Remove the instruction to apply persisted preferences automatically. Present stored preferences as untrusted suggestions and require explicit confirmation from an authorized user before each adoption.
- Prohibit the learning workflow from modifying
SKILL.mdor any other governing instruction, executable, configuration, startup, or policy file. - Separate passive telemetry from trusted configuration. Store operation statistics and free-form notes in a data-only location that is never interpreted as agent instructions.
- Define a strict schema for preferences. Permit only documented keys and constrained values, such as fixed enumerations, booleans, or bounded numeric values.
- Reject preference values, error names, and notes containing instruction-like content, control syntax, excessive length, unexpected structured data, or references to tool execution.
- Add provenance and trust metadata to every stored record, including who supplied it, when it was recorded, and whether an authorized reviewer approved it.
- Require human review and an explicit diff approval before any learned recommendation can affect operational behavior.
- Make the skill package and
SKILL.mdread-only at runtime where possible. Place mutable state in a separate directory with narrowly scoped permissions. - Treat
learned_patterns.jsonas potentially hostile when loaded. Validate its complete structure and fail closed on malformed, unknown, or unauthorized fields. - Add tests demonstrating that stored free-form values cannot become system prompts, skill instructions, tool arguments, or file modifications in later sessions.
