T02 · Agent Memory Poisoning
- Location
scripts/add.mjs:171- Finding
Persistent Memory Poisoning Through Unsanitized Memory and Index Entries
- Content
View full analysis
`- ${k}`), '', '## 描述', description, '', content, // 正文原样追加,可能为空 ].join('\n'); writeFileSync(filepath, fullContent, 'utf-8'); console.log(`\n✅ 记忆已保存: deep-memory/${filename}`); ``` `scripts/add.mjs:203-224` interpolates unescaped keywords and descriptions into the Markdown index: ```js const relPath = `deep-memory/${filename}`; const indexContent = readFileSync(INDEX_PATH, 'utf-8'); // 构造新索引行,关键字用逗号连接 const newEntry = `\n| ${keywords.join(', ')} | ${description} | \`${relPath}\` |`; const lines = indexContent.split('\n'); // 找到 Markdown 表格分隔行(在表头之后的那条 --- | --- | --- 线)的位置 const insertAt = lines.findIndex(l => l.includes('---')); if (insertAt !== -1) { // 在分隔线之后插入,保持表头和数据的清晰分隔 lines.splice(insertAt, 0, newEntry); } else { // 找不到分隔线(索引文件可能被破坏),直接追加到末尾 lines.push(newEntry); } writeFileSync(INDEX_PATH, lines.join('\n'), 'utf-8'); console.log('✅ 索引已更新'); ``` `scripts/query.mjs:114-125` parses index rows using an unsafe delimiter-based parser and returns the stored path without validating its destination: ```js const [kw, desc, filePath] = parts; const kwLower = kw.toLowerCase(); const keyLower = keyword.toLowerCase(); const matched = kwLower.includes(keyLower) || keyLower.includes(kwLower); if (matched) { // 去除文件路径两端的反引号(如 "`deep-memory/xxx.md`" → "deep-memory/xxx.md") results.push({ keyword: kw, description: desc, filePath: filePath.replace(/`/g, ''), }); } ``` The documented retrieval workfl ...[truncated 3169 chars]- Remediation
View remediation
