T02 · Agent Memory Poisoning
- Location
scripts/scribe.js:214- Finding
Untrusted Transcript Content Can Poison Persistent Agent Memory
- Content
View full analysis
Vulnerability Details
File Location:
scripts/scribe.js, lines 214-242
Vulnerability Type: Persistent memory poisoning through untrusted conversation content
Risk Level: HighVulnerable Code
javascript async function summarize(turns, label) { const conversation = turns.map(t => `${t.role === 'user' ? 'User' : 'Agent'}: ${t.text}`).join('\n\n'); const prompt = `You are a memory scribe for an AI agent. Extract key events, decisions, facts, and actions from this conversation excerpt. Write concise bullet points — as many as needed to capture everything significant. Focus on: things created/built, decisions made, problems solved, important facts learned, notable exchanges. Skip small talk and filler. Be specific and factual. Session: ${label} Conversation: ${conversation} Output ONLY bullet points starting with "- ". No headers, no preamble.`; return llmRequest(prompt); } // ── Memory writing ──────────────────────────────────────────────────────────── function appendToMemory(summary, label) { const date = new Date().toISOString().slice(0, 10); const file = path.join(memoryDir, `${date}.md`); const timestamp = new Date().toISOString().slice(11, 16) + ' UTC'; const header = fs.existsSync(file) ? '' : `# ${date}\n\n`; const block = `\n## Scribe [${timestamp}] ${label}\n\n${summary}\n`; fs.mkdirSync(memoryDir, { recursive: true }); fs.appendFileSync(file, header + block); return file; }Technical Analysis
User and assistant transcript text is interpolated directly into the summarization prompt without a strong trust boundary, structured data encoding, or an instruction explicitly requiring the model to treat the transcript solely as untrusted quoted data. The resulting model output is then appended directly to a persistent daily memory file.
The transcript filtering in
extractTurnsremoves several known metadata wrappers, but it does not prevent or ...[truncated 2693 chars]- Remediation
View remediation
Remediation Suggestions
- Treat all transcript content as untrusted data and state this explicitly in the summarizer's higher-priority instructions.
- Use provider-supported system and user message separation. Put security constraints in a system message and submit the transcript as a separately encoded user-data object.
- Instruct the model never to preserve commands, policies, credentials, authorization claims, or future-facing behavioral instructions found in transcripts.
- Request a strict structured response, such as validated JSON containing factual event categories, instead of unrestricted Markdown.
- Apply deterministic post-processing before persistence. Reject bullets containing instruction-like language, authorization changes, secrets, URLs, executable commands, or claims that cannot be tied to identified transcript turns.
- Preserve provenance with every memory item, including session ID, source role, source entry index, and a marker such as
trust: unverified. - Require review or confirmation before ingesting security-sensitive memories into downstream systems.
- Separate descriptive memories from executable agent instructions. Downstream agents should be told that recalled memories are untrusted historical claims and cannot override current instructions or authorization controls.
- Consider allowlisting the types of information that may be persisted, rather than attempting to block individual injection phrases.
