T02 · Agent Memory Poisoning
- Location
memory/mia-memory.mjs:329- Finding
Untrusted Persistent Memory Can Influence Future Agent Plans
- Content
View full analysis
Vulnerability Details
File Location:
memory/mia-memory.mjs:329-343,mia-memory/mia-memory.mjs:329-343,planner/mia-planner.mjs:58-77, andmia-planner/mia-planner.mjs:58-77
Vulnerability Type: Persistent memory poisoning through unsanitized historical plans
Risk Level: MediumVulnerable Code
Memory records are accepted and persisted without schema validation, provenance checks, or content sanitization:
js function storeRecord(entry) { const record = { timestamp: new Date().toISOString(), ...entry }; // If efficiency metrics are absent, add default values if (!record.efficiency && record.execution) { record.efficiency = { search_count: record.execution.length, step_count: (record.steps || []).length, success: true }; } return storeWithOptimization(record); }Historical plan content is subsequently inserted directly into the model prompt:
js async function generatePlan(question, referencePlan = null) { const prompt = referencePlan !== null ? REFERENCE_PROMPT.replace('{historicalPlan}', referencePlan).replace('{question}', question) : BASE_PROMPT.replace('{question}', question); try { // Request generation continues using the constructed promptThe actual source uses equivalent non-English template placeholder names; the security-relevant behavior is direct substitution of
referencePlanandquestioninto the prompt.Technical Analysis
The
storecommand accepts arbitrary JSON and spreads every supplied property into a persistent record. It does not enforce a schema, constrain plan content, record provenance, distinguish trusted instructions from untrusted data, or reject instruction-like text.The documented workflow allows a retrieved historical plan to be passed to the planner through the
--referenceargument. The planner inserts that text directly into the model ...[truncated 1985 chars]- Remediation
View remediation
Remediation Suggestions
- Define and enforce a strict schema for stored records, including expected types, maximum lengths, and permitted fields.
- Reject unknown fields rather than spreading arbitrary input into the persistent record.
- Record provenance, trust level, creator identity, and validation status for every memory.
- Treat all historical plans as untrusted data and clearly delimit them in the model prompt.
- Add explicit planner instructions that content inside the historical-plan section must never override planner policies or request unrelated actions.
- Normalize stored plans into structured, allowlisted action metadata instead of retaining unrestricted instruction text where possible.
- Validate generated steps against an action and tool allowlist before sending them to an executor.
- Require user confirmation for sensitive or privileged actions derived from historical memory.
- Add retention, review, quarantine, and deletion controls for suspicious memories.
- Apply the same changes to both duplicate implementations under
memory/andmia-memory/.
