T02 · Agent Memory Poisoning
- Location
scripts/learning_store.py:315- Finding
Persistent Prompt Injection Through the Error Book
- Content
View full analysis
None: if normalized_verdict(event.get("verdict")) != "corrected": return errors = event.get("errors") or [] if not errors: return lines = [f"\n### Correction {timestamp}\n", f"- Original: {event.get('input', '')}\n"] if event.get("correction"): lines.append(f"- Correction: {event['correction']}\n") for error in errors: if not isinstance(error, dict): continue category = error.get("category", "unknown") span = error.get("span", "") fix = error.get("fix", "") note = error.get("note", "") lines.append(f"- [{category}] {span} -> {fix}. {note}\n") with (data_dir / "error-book.md").open("a", encoding="utf-8") as fh: fh.writelines(lines) ``` The persisted file is later designated as an input source: ```markdown ### `/review` Pick 3-5 recurring error patterns from `error-book.md` and recent events. Give short examples and one tiny practice task. ``` ### Technical Analysis The `append_error_book` function interpolates multiple untrusted event fields directly into an agent-readable Markdown document: - `input` - `correction` - `category` - `span` - `fix` - `note` The implementation performs no schema validation, newline filtering, Markdown escaping, instruction-content neutralization, or meaningful length restriction before persistence. An attacker can therefore place line breaks, headings, quoted instructions, or other prompt-like content into these fields and alter the apparent structure of `error-book.md`. This becomes an agent memory poisoning issue because `SKILL.md` explicitly in ...[truncated 2435 chars]- Remediation
View remediation
