T02 · Agent Memory Poisoning
Error
- Location
- scripts/mem0-add.js:26
- Finding
- Caller-Controlled User Identifiers Permit Cross-User Memory Poisoning, Disclosure, and Deletion## Vulnerability Details **File Location**: `scripts/mem0-add.js:26-29, 45-49`; `scripts/mem0-search.js:23-35`; `scripts/mem0-list.js:13-21`; `scripts/mem0-delete.js:22-41` **Vulnerability Type**: Missing authorization and insecure object ownership enforcement **Risk Level**: High ### Vulnerable Code `scripts/mem0-add.js:26-29, 45-49`: ```javascript if (arg.startsWith("--messages=")) { try { messages = JSON.parse(arg.substring(11)); } catch (e) { console.error("Error parsing messages JSON:", e.message); process.exit(1); } } else if (arg.startsWith("--user=")) { userId = arg.split("=")[1]; } else if (!arg.startsWith("--")) { text = arg; } let result; if (messages) { result = await memory.add(messages, { userId }); } else { result = await memory.add(text, { userId }); } ``` `scripts/mem0-search.js:23-35`: ```javascript for (const arg of args.slice(1)) { if (arg.startsWith("--limit=")) { limit = parseInt(arg.split("=")[1]); } else if (arg.startsWith("--user=")) { userId = arg.split("=")[1]; } } try { const memory = getMem0Instance(); const results = await memory.search(query, { userId, limit }); ``` `scripts/mem0-list.js:13-21`: ```javascript for (const arg of args) { if (arg.startsWith("--user=")) { userId = arg.split("=")[1]; } } try { const memory = getMem0Instance(); const response = await memory.getAll({ userId }); ``` `scripts/mem0-delete.js:22-41`: ```javascript for (const arg of args) { if (arg === "--all") { deleteAll = true; } else if (arg.startsWith("--user=")) { userId = arg.split("=")[1]; } else if (!arg.startsWith("--")) { memoryId = arg; } } try { const memory = getMem0Instance(); if (deleteAll) { await memory.deleteAll({ userId }); console.log(`✓ All memories deleted for user: ${userId}`); } else i ...[truncated 2794 chars]
- Remediation
- ## Remediation Suggestions - Remove the caller-controlled `--user` option from normal Agent-facing commands. - Derive the user identifier from authenticated, trusted session context. - Enforce ownership checks inside the storage layer rather than relying only on CLI argument handling. - Scope individual deletion by both memory ID and authenticated owner. - Reject empty, malformed, unknown, or unauthorized user identifiers. - Maintain physically or cryptographically separated stores for different users where possible. - Require explicit confirmation or a separate privileged capability for bulk deletion. - Treat retrieved memory as untrusted data and prevent it from overriding system or developer instructions. - Record security audit events for memory creation, enumeration, and deletion without logging sensitive memory content. - Add tests proving that one authenticated user cannot add, read, search, or delete another user's records.
