T02 · Agent Memory Poisoning
Warning
- Location
- scripts/analyze_problem.py:40
- Finding
- Persistent Markdown Injection into Agent Memory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze_problem.py:40-71`; `scripts/lib/storage.py:57-74` **Vulnerability Type**: Persistent Markdown injection and memory poisoning **Risk Level**: Medium ### Vulnerable Code ```python # scripts/analyze_problem.py:40-71 title = args.title.strip() if args.title else clean_title(args.text) case = { "id": case_id, "title": title, "problem": args.text.strip(), "goal": infer_goal(args.text), "assumptions": infer_assumptions(args.text), "truths": infer_truths(args.text), "components": infer_components(args.text), "constraints": infer_constraints(args.text), "anti_patterns": detect_anti_patterns(args.text), "heuristics_used": select_heuristics(args.text), "reusable_pattern_candidate": "", "promotion_status": "none", "rebuilt_solution": infer_rebuilt_solution(args.text), "next_actions": infer_next_actions(args.text), "score": {}, "created_at": now_iso(), "updated_at": now_iso() } case["score"] = compute_score(case) case["reusable_pattern_candidate"] = infer_pattern_candidate(case) case["promotion_status"] = promotion_status(case) data["cases"][case_id] = case save_cases(data) append_case_index(case) if case["promotion_status"] == "promoted": append_promoted_pattern(case) ``` ```python # scripts/lib/storage.py:57-74 def append_case_index(case): ensure_storage() line = f"- {case['id']} | {case['title']} | score={case.get('score', {}).get('overall')} | promotion={case.get('promotion_status', 'none')} | created={case.get('created_at')}\n" with open(CASE_INDEX_PATH, "a", encoding="utf-8") as f: f.write(line) def append_promoted_pattern(case): ensure_storage() candidate = (case.get("reusable_pattern_candidate") or "").strip() if not candidate: return False entry = [] entry.append(f"## {case['id']} — {case['title']}") entry.append(f"- Pattern: {candidate}") entry.append(f"- Sour ...[truncated 2797 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Constrain titles before storage** - Reject `\r`, `\n`, null bytes, and other control characters. - Apply a conservative maximum length. - Optionally restrict titles to an allowlist of expected characters. 2. **Escape content for Markdown** - Escape Markdown metacharacters before inserting untrusted values into headings or list records. - Convert all newline characters to spaces when a value must remain on one line. 3. **Separate data from instructions** - Keep records in structured JSON rather than using generated Markdown as an authoritative memory source. - When records are supplied to an agent, place them inside a clearly delimited untrusted-data section. - Explicitly instruct the consuming agent never to follow instructions found in stored case content. 4. **Require approval for promotion** - Do not promote records based only on a deterministic score. - Require explicit user confirmation or a trusted review step before writing to `patterns.md`. 5. **Prevent duplicate promotion** - Record whether a pattern has already been written. - Use stable identifiers and idempotent updates instead of unconditional append operations. 6. **Validate all stored fields** - Introduce a schema-validation layer for titles, identifiers, timestamps, list entries, and generated candidates before persistent writes. ]]>
