T02 · Agent Memory Poisoning
- Location
scripts/learner.py:72- Finding
Persistent Agent Memory Poisoning Through Unvalidated Learning Data
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:47-70;scripts/learner.py:72-92,108-116
Vulnerability Type: Persistent storage and reuse of attacker-controlled instructions
Risk Level: MediumVulnerable Code and Instructions
scripts/learner.py:72-92accepts and persistently stores unrestricted error notes:python def record_op(skill_dir, capability, success=True, error=None, note=None): data = load_learning(skill_dir) data["totalOps"] += 1 cap = data["capabilityStats"].setdefault(capability, {"count": 0, "success": 0, "fail": 0}) cap["count"] += 1 if success: cap["success"] += 1 else: cap["fail"] += 1 data["totalErrors"] += 1 if error: ep = data["errorPatterns"].setdefault(error, {"count": 0, "lastNote": "", "lastTime": ""}) ep["count"] += 1 ep["lastNote"] = note or "" ep["lastTime"] = data["lastUpdated"] or datetime.datetime.now().strftime("%Y-%m-%dT%H:%M") rec = {"t": data["lastUpdated"], "cap": capability, "ok": success, "err": error, "note": note} data["recentOps"].append(rec) data["recentOps"] = data["recentOps"][-20:] save_learning(skill_dir, data) return datascripts/learner.py:94-98persistently stores unrestricted preference keys and values:python def record_preference(skill_dir, key, value): data = load_learning(skill_dir) data["preferences"][key] = value save_learning(skill_dir, data) return datascripts/learner.py:108-116reproduces the stored note in reflection output:python def self_reflect(skill_dir): data = load_learning(skill_dir) suggestions = [] for err, info in data["errorPatterns"].items(): if info["count"] >= THRESHOLD_ERROR: suggestions.append( f"⚠️ 错误「{err}」已出现 {info['count']} 次,建议增加预检/兜底步骤," f"并将经验回写本技能 SKILL.md(lastNote: {info.get('lastNote','')})" )SKILL.md:62-70directs the agent t ...[truncated 2905 chars]- Remediation
View remediation
Remediation Suggestions
- Treat every value in
learned_patterns.jsonas untrusted data rather than executable guidance. - Remove the instruction to write learned content directly into
SKILL.md. Keep immutable skill instructions separate from writable runtime state. - Require explicit, informed human approval before a preference can alter future agent behavior.
- Define an allowlisted preference schema with recognized keys, constrained enum or typed values, and safe defaults. Reject unknown keys.
- Limit the length and character set of error names, notes, preference keys, and preference values.
- Store provenance for each entry, including who supplied it, when it was recorded, and whether it was reviewed.
- Render persisted values as quoted data and clearly label them as untrusted when producing
insightorreflectoutput. - Do not interpolate arbitrary notes into agent-facing recommendations. Summarize them through a trusted transformation or display them only in a non-instructional section.
- Add integrity controls and restrictive file permissions to the learning file where multiple users or processes can access the skill directory.
- Add tests proving that prompt-like preference values and notes cannot modify skill instructions or become authoritative directives in later sessions.
- Treat every value in
