- Location
- hook/handler.js:128
- Finding
- Untrusted Cross-Agent Memories Are Persistently Injected into Privileged Bootstrap Context<![CDATA[
## Vulnerability Details
**File Location**: `hook/handler.js:128-161, 349-421, 552-571`
**Vulnerability Type**: Persistent memory poisoning and cross-agent prompt injection
**Risk Level**: Critical
### Vulnerable Code
```js
async function queryTopMemories(pool, { limit = 8, minImportance = 5, agentName = null }) {
// Split into own-agent + cross-agent slots to ensure visibility across agents
const crossSlots = Math.max(2, Math.floor(limit * 0.3));
const ownSlots = limit - crossSlots;
return withRetry(async () => {
const ownFilter = agentName
? `AND (agent = $3 OR agent IS NULL)`
: '';
const ownParams = agentName
? [minImportance, ownSlots, agentName]
: [minImportance, ownSlots];
const { rows: ownRows } = await pool.query(
`SELECT content, tier, importance, type, agent, context
FROM brainx_memories
WHERE tier IN ('hot', 'warm')
AND importance >= $1
AND superseded_by IS NULL
${ownFilter}
ORDER BY importance DESC, last_seen DESC NULLS LAST, created_at DESC
LIMIT $2`,
ownParams
);
const crossFilter = agentName
? `AND agent IS DISTINCT FROM $3 AND agent IS NOT NULL`
: '';
const crossParams = agentName
? [minImportance, crossSlots, agentName]
: [minImportance, crossSlots];
const { rows: crossRows } = await pool.query(
`SELECT content, tier, importance, type, agent, context
FROM brainx_memories
WHERE tier IN ('hot', 'warm')
AND importance >= $1
AND superseded_by IS NULL
${crossFilter}
ORDER BY
CASE WHEN 'cross-agent' = ANY(tags) THEN 1 ELSE 0 END DESC,
importance DESC, last_seen DESC NULLS LAST, created_at DESC
LIMIT $2`,
crossParams
);
return [...ownRows, ...crossRows];
}, "queryTopMemories");
}
```
```js
function buildMemorySection(agentName, timestamp, teamMems, ownMems) {
const lines = [BRAINX_START,
...[truncated 4532 chars]
- Remediation
- <![CDATA[
## Remediation Suggestions
1. Do not write untrusted memory text into privileged bootstrap files such as `MEMORY.md`, `AGENTS.md`, or `SOUL.md`.
2. Pass retrieved memories through a dedicated untrusted-data channel that explicitly tells the model the content is reference material, not instructions.
3. Implement per-agent access controls and deny cross-agent retrieval by default.
4. Require verified provenance before a memory is eligible for bootstrap injection.
5. Store and inject structured facts rather than unrestricted Markdown.
6. Detect and quarantine imperative, meta-instruction, tool-invocation, credential-request, and safety-override patterns.
7. Add explicit delimiters and escape Markdown constructs, while recognizing that escaping alone is not a complete prompt-injection defense.
8. Require human approval for memories that could alter agent behavior.
9. Add expiration, revocation, and audit mechanisms for all injected memories.
10. Test with adversarial memories that attempt to override instructions, invoke tools, exfiltrate data, or propagate between agents.
]]>