T02 · Agent Memory Poisoning
- Location
scripts/kg.py:167- Finding
Persistent Agent Memory Poisoning Through Unsanitized Fact Content
- Content
View full analysis
str: active = [it for it in items if it.get("status") == "active"] # stable-ish ordering: newest first by timestamp, then id def sort_key(it: Dict[str, Any]): ts = str(it.get("timestamp") or "") return (ts, str(it.get("id") or "")) active.sort(key=sort_key, reverse=True) lines = [f"# {slug}", "", f"Updated: {today_date()}", ""] for it in active[:max_lines]: fact = str(it.get("fact") or "").strip() if not fact: continue lines.append(f"- {fact}") if len(active) > max_lines: lines.append(f"- …and {len(active) - max_lines} more active facts") lines.append("") return "\n".join(lines) ``` The untrusted value originates from the command-line argument and is passed directly into persistent storage: ```python p_add.add_argument("--fact", required=True) ``` ```python if args.cmd == "add": new_id = add_fact( kind=kind, slug=slug, fact=args.fact, category=args.category, source=args.source, timestamp=args.timestamp, ) if args.summarize: summarize_entity(kind, slug) print(new_id) return ``` ### Technical Analysis `--fact` is treated as unrestricted text. `add_fact()` persists the supplied value in `items.json` with an active status, and `build_summary()` subsequently interpolates the value directly into `summary.md`: ```python lines.append(f"- {fact}") ``` No trust classification, instruct ...[truncated 2212 chars]- Remediation
View remediation
