T02 · Agent Memory Poisoning
Warning
- Location
- auto_log_skill.py:95
- Finding
- Persistent Agent Memory Poisoning Through Unescaped Log Entries<![CDATA[ ## Vulnerability Details **File Location**: `auto_log_skill.py:95-124`, `auto_log_skill.py:135-161`, and `auto_log_skill.py:175-201` **Vulnerability Type**: Persistent injection of attacker-controlled content into Agent memory **Risk Level**: Medium ### Vulnerable Code ```python # auto_log_skill.py:95-124 log_path = self.get_today_log_path() if not log_path.exists(): self.create_daily_log() try: with open(log_path, 'r', encoding='utf-8') as f: content = f.read() section_marker = f"## {section}" section_pos = content.find(section_marker) timestamp = datetime.now().strftime('%H:%M') if section_pos == -1: # Section not found — append at end new_content = f"\n### {section} ({timestamp})\n- {event}\n" else: new_content = f"\n- {timestamp} {event}" next_section_pos = content.find("\n## ", section_pos + 1) if next_section_pos == -1: next_section_pos = len(content) insert_pos = content.find("\n", section_pos) while insert_pos < next_section_pos and content[insert_pos:insert_pos + 3] == "\n- ": insert_pos = content.find("\n", insert_pos + 1) content = content[:insert_pos] + new_content + content[insert_pos:] with open(log_path, 'w', encoding='utf-8') as f: f.write(content) return True with open(log_path, 'a', encoding='utf-8') as f: f.write(new_content) ``` ```python # auto_log_skill.py:135-161 try: with open(log_path, 'r', encoding='utf-8') as f: content = f.read() section_marker = "## ✅ Tasks" section_pos = content.find(section_marker) if section_pos == -1: new_line = f"\n| {task} | {status} | {result} |\n" content = content.rstrip() + f"\n\n## ✅ Tasks\n| Task | Status | Result |\n|------|--------|--------|\n{new_line}\n" else: table_end = content.find("\n\n", section_pos) if table_end == -1: table_end = len(content) ...[truncated 2902 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat every value supplied to logging APIs as untrusted data. 2. Reject or normalize control characters and line breaks when entries are intended to occupy a single Markdown line or table cell. 3. Escape Markdown structural characters, especially pipes in table cells and heading/list syntax at the beginning of lines. 4. Validate `section` against a fixed allowlist rather than allowing arbitrary headings. 5. Apply reasonable maximum lengths to all fields. 6. Prefer a structured format such as JSON with separate fields for content, timestamp, source, and trust level. 7. If Markdown output is required, render it from structured records rather than modifying Markdown through string concatenation. 8. Mark stored content explicitly as untrusted historical data. 9. Ensure downstream Agent prompts state that log contents must never be interpreted as executable instructions. 10. Add tests containing embedded newlines, headings, Markdown table separators, comments, and prompt-injection text. ]]>
