Module: B3 — Memory and Context Poisoning Diagram count: 5 Tool: Mermaid (primary). Each diagram validated in Mermaid Live Editor.
Type: Comparison / overlay Purpose: The foundational mental model of the module. An agent has two memory surfaces, and the distinction is load-bearing: long-term memory persists across sessions (survives logout/login), the context window is per-session (dies with the session). Persistence is the single property that makes memory a categorically different attack surface from the context window. B2's five layers operate inside the context window; this module's attacks and defenses extend into the persistent surface. Reading the diagram: Two horizontal bands. The top (long-term memory) is durable — it survives the session boundary. The bottom (context window) is ephemeral — it dies when the session ends. The arrow between them is the memory load that happens at session start, before the user types anything. Note that B2's layers all sit inside the context window and never touch the load path.
flowchart LR
subgraph LTM["LONG-TERM MEMORY — persists across sessions"]
direction TB
L1["stored OUTSIDE the model<br/>DB · vector store · KV cache · files"]
L2["survives logout / login / refresh<br/>version bump / session timeout"]
L3["loaded into context at session START<br/>before the user types anything"]
end
subgraph CW["CONTEXT WINDOW — per-session"]
direction TB
C1["system prompt · conversation history<br/>retrieved context · tool outputs (this turn)"]
C2["born at session start<br/>DIES at session end"]
C3["B2's 5 layers operate HERE<br/>tag · isolate · taint · gate · minimize"]
end
LTM ===|"memory load<br/>at session start<br/>(trusted by default)"| CW
style LTM fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#e4e4e8
style CW fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
style L1 fill:#101018,stroke:#f08080,color:#e4e4e8
style L2 fill:#101018,stroke:#f08080,color:#e4e4e8
style L3 fill:#101018,stroke:#f08080,color:#e4e4e8
style C1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C2 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C3 fill:#101018,stroke:#5eead4,color:#e4e4e8
Note: The asymmetry is the point. Everything B2 defends is inside the context window and dies with the session. Long-term memory survives — and because it is loaded as trusted by default, a poisoned entry routes around all five B2 layers. B3 extends the defense into the persistent surface.
Type: Timeline / sequence Purpose: The centerpiece attack of the module, made visual. The sleeper attack (Course 1 Module 4.3): inject in session 1, the payload sleeps in memory, it activates in session 2. The fuse crosses the session boundary. The critical failure is not the injection in session 1 — it is the unvalidated read in session 2, where the memory loader promotes a poisoned entry to trusted context without re-checking it. Reading the diagram: Two sessions separated by the session boundary (the fuse). In session 1 the seed is planted and is inert. Persistence carries it across. In session 2 the seed loads as trusted and fires. The red callout marks the load-bearing failure: the read path trusts the write path unconditionally.
flowchart TB
subgraph S1["SESSION 1 — THE INJECTION"]
direction TB
A1["attacker delivers payload"]
A2["agent writes SEED to memory<br/>(via save_to_memory, or ingest, or summary)"]
A3["seed is INERT this session<br/>nothing visible happens"]
A1 --> A2 --> A3
end
BOUND["SESSION BOUNDARY — THE FUSE<br/>logout · login · days pass<br/>user forgets session 1"]:::warn
subgraph S2["SESSION 2 — THE ACTIVATION"]
direction TB
B1["user starts fresh session"]
B2["memory loader runs<br/>pulls seed into context as TRUSTED"]
B3["no tag (B2 L1 missed it)<br/>no gate (B2 L3 missed it)<br/>seed is already in the window"]
B4["SEED FIRES<br/>agent obeys as if system prompt"]
B1 --> B2 --> B3 --> B4
end
FAIL["THE LOAD-BEARING FAILURE<br/>unvalidated READ in session 2<br/>memory trusted by default<br/>nothing re-checks the seed"]:::danger
S1 --> BOUND --> S2
B2 -. fails here .-> FAIL
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style S1 fill:#14141f,stroke:#f0a868,color:#e4e4e8
style S2 fill:#14141f,stroke:#f08080,color:#e4e4e8
style A1 fill:#101018,stroke:#f0a868,color:#e4e4e8
style A2 fill:#101018,stroke:#f0a868,color:#e4e4e8
style A3 fill:#101018,stroke:#f0a868,color:#e4e4e8
style B1 fill:#101018,stroke:#f08080,color:#e4e4e8
style B2 fill:#101018,stroke:#f08080,color:#e4e4e8
style B3 fill:#101018,stroke:#f08080,color:#e4e4e8
style B4 fill:#101018,stroke:#f08080,stroke-width:1.5px,color:#f08080
Note: The two events may be days apart, in different contexts, under different account states — which makes the sleeper attack harder to attribute than a same-session injection. By the time it fires, the trail back to session 1 is cold. The defense (B3.3) does not try to catch the injection in session 1; it ensures the seed can never be written, and that any residual poison is tagged on read.
Type: Data-flow / pipeline Purpose: How a poisoned chunk travels from a writable source through the retrieval store into the context window. The retrieval store is written by many paths (user uploads, crawled content, agent summaries, cross-tenant leaks) — not all trusted. Once a poisoned chunk is in the index, retrieval is the activation mechanism: the attacker crafts the chunk to be semantically similar to the victim's queries, so the poison is fetched, inserted as data-but-obeyed-as-instruction, and the agent complies. This is indirect injection (B2's most dangerous class) with the persistence property of memory. Reading the diagram: Left to right — the write paths into the index (red = untrusted), the poisoned chunk persisting, the retrieval fetching it on a relevant query, and the injection into the context window. The green callout marks the defense: retrieved-content taint tagging (B2 Layer 1) connects B3 retrieval defense to the B2 stack.
flowchart LR
subgraph WRITE["WRITE PATHS INTO THE INDEX"]
direction TB
W1["user-uploaded doc"]:::danger
W2["crawled / synced content<br/>(compromised wiki page)"]:::danger
W3["agent-generated summary<br/>(laundered injection)"]:::danger
W4["cross-tenant leak<br/>(weak isolation)"]:::danger
end
IDX[("RETRIEVAL STORE<br/>vector / keyword index<br/>PERSISTS — poison stays<br/>until found + removed")]:::warn
subgraph RETRIEVE["RETRIEVAL — THE ACTIVATION"]
direction TB
R1["victim issues a query"]
R2["poisoned chunk is semantically similar<br/>→ it is FETCHED"]
R3["chunk inserted into context window<br/>as DATA — but obeyed as INSTRUCTION"]
R1 --> R2 --> R3
end
DEF["DEFENSE — taint tagging<br/>retrieved chunk tagged UNTRUSTED (B2 L1)<br/>taint gate (B2 L3) blocks high-impact calls<br/>provenance filtering + re-ranking upstream"]:::good
WRITE --> IDX
IDX --> RETRIEVE
R3 -. defended by .-> DEF
classDef danger fill:#101018,stroke:#f08080,color:#e4e4e8
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style W1 fill:#101018,stroke:#f08080,color:#e4e4e8
style W2 fill:#101018,stroke:#f08080,color:#e4e4e8
style W3 fill:#101018,stroke:#f08080,color:#e4e4e8
style W4 fill:#101018,stroke:#f08080,color:#e4e4e8
style IDX fill:#14141f,stroke:#f0a868,stroke-width:2px,color:#f0a868
style R1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style R2 fill:#101018,stroke:#f08080,color:#e4e4e8
style R3 fill:#101018,stroke:#f08080,stroke-width:1.5px,color:#f08080
Note: The retrieval store is a memory surface, and it is the most commonly writable one — ingestion pipelines (sync, crawl, bulk import) may bypass the model-propose/harness-validate gate entirely. The defense is not to make the store unwritable; it is to treat every retrieved chunk as untrusted by default (B2 Layer 1) unless its provenance proves otherwise, so the taint gate applies.
Type: Process / control flow
Purpose: The central defense of the module, made visual. The model PROPOSES memory writes; the harness VALIDATES them; only the harness COMMITS. Three checks in order — provenance (where did it come from), trust level (is the source trusted), content (does it look like an injection). The conjunction of untrusted provenance AND instruction-like content is the sleeper-attack signature that CHECK 3 blocks deterministically. The model never touches the store directly.
Reading the diagram: The model emits a proposal (content + justification + provenance). The gate runs three checks. Any failure → DENY (logged, surfaced). All pass → COMMIT with provenance + trust + decision tag. The unconditional write path (the save_to_memory tool) does not exist.
flowchart TB
PROP["MODEL PROPOSES a write<br/>content + justification + provenance<br/>(the model NEVER touches the store)"]:::accent
GATE["HARNESS VALIDATION GATE<br/>three checks, in order"]
C1["CHECK 1 — PROVENANCE<br/>where did the content come from?<br/>user_direct · retrieval · tool · agent_inferred"]:::check
C2["CHECK 2 — TRUST LEVEL<br/>trusted · semi_trusted · untrusted<br/>(derived from provenance)"]:::check
C3["CHECK 3 — CONTENT<br/>does it look like an injection?<br/>detector + sleeper-signature heuristic"]:::check
DENY["DENY — log + surface<br/>injection_detected · untrusted_instruction_like<br/>· provenance_violation"]:::danger
COMMIT["COMMIT — only the harness writes<br/>entry tagged: source + trust_level<br/>+ timestamp + writer + validation_result"]:::good
READ["READ PATH (separate)<br/>load entry → tag by trust level<br/>untrusted entries get B2 L1 tag<br/>→ taint gate applies on next session"]:::check
PROP --> GATE
GATE --> C1 --> C2 --> C3
C1 -. fail .-> DENY
C2 -. untrusted + instruction-like .-> DENY
C3 -. fail .-> DENY
C3 -. all pass .-> COMMIT
COMMIT -. read later .-> READ
classDef accent fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
classDef check fill:#101018,stroke:#5eead4,color:#e4e4e8
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style GATE fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
style PROP fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
style C1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C2 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C3 fill:#101018,stroke:#5eead4,color:#e4e4e8
style DENY fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style COMMIT fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style READ fill:#101018,stroke:#f0a868,color:#e4e4e8
Note: The load-bearing line is CHECK 3's conjunction:
if (trustLevel === "untrusted" && looksLikeInstruction(...)). A trusted user directly stating a preference passes. An untrusted chunk that happens to be factual passes. The conjunction catches the payload that is both untrusted-sourced and instruction-shaped — which is exactly what a sleeper seed is. The gate's strength is not perfection; it is the removal of the unconditional write path.
Type: Propagation / cascade Purpose: Why a single poisoned or hallucinated result is worse than a localized error — the downstream risk OWASP ranks as ASI06. The agent retrieves or recalls one false premise, treats it as ground truth, and builds all subsequent reasoning on top of it. The error propagates through the chain: false premise → flawed reasoning → flawed action → recorded result → further reasoning. By the time the user sees the output, the original error is buried under layers of plausible derivation, and if the premise was persisted to memory, the cascade recurs every session. Reading the diagram: Top to bottom — the cascade. The poison enters (from memory or retrieval), becomes a premise, drives reasoning, drives an action, the action's result is recorded, and further reasoning builds on it. Each step inherits the original error. The amber callout marks the source: poisoned memory is the most reliable cascade trigger, because the agent treats its own memory as authoritative.
flowchart TB
SRC["POISONED / HALLUCINATED PREMISE<br/>from memory (ASI04) or retrieval (RAG poison)"]:::danger
P1["agent treats premise as GROUND TRUTH<br/>(memory = authoritative; retrieval = data-but-obeyed)"]:::danger
R1["agent REASONS on the false premise"]
ACT["agent takes an ACTION<br/>calls a tool · generates output<br/>based on the flawed reasoning"]
REC["action result is RECORDED<br/>(to memory · to context · to a log)"]
R2["agent reasons FURTHER<br/>on top of the recorded result"]
OUT["USER SEES THE OUTPUT<br/>internally consistent chain<br/>but the FOUNDATION was poisoned"]:::warn
CASCADE["THE CASCADE<br/>every downstream step inherits<br/>the original error<br/>the longer it runs, the deeper it buries"]:::danger
SRC --> P1 --> R1 --> ACT --> REC --> R2 --> OUT
R2 -. loop .-> R1
P1 -. drives .-> CASCADE
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
style SRC fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style P1 fill:#101018,stroke:#f08080,color:#f08080
style R1 fill:#101018,stroke:#f08080,color:#e4e4e8
style ACT fill:#101018,stroke:#f08080,color:#e4e4e8
style REC fill:#101018,stroke:#f0a868,color:#e4e4e8
style R2 fill:#101018,stroke:#f08080,color:#e4e4e8
style OUT fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
style CASCADE fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
Note: A single hallucination is a localized error the user corrects. A cascading hallucination is a contaminated reasoning chain — and the cascade is faster and harder to interrupt when the foundation is the agent's own prior memory. The defense is not to catch each hallucination individually; it is to prevent poisoned premises from entering memory (B3.3 gate) and to detect propagation when it starts (audit the reasoning chain, purge the poisoned premise from the store).
# Diagrams — Module B3: Memory and Context Poisoning
**Module**: B3 — Memory and Context Poisoning
**Diagram count**: 5
**Tool**: Mermaid (primary). Each diagram validated in [Mermaid Live Editor](https://mermaid.live).
---
## Diagram 1 — The Two Memory Surfaces
**Type**: Comparison / overlay
**Purpose**: The foundational mental model of the module. An agent has two memory surfaces, and the distinction is load-bearing: **long-term memory persists across sessions** (survives logout/login), **the context window is per-session** (dies with the session). Persistence is the single property that makes memory a categorically different attack surface from the context window. B2's five layers operate inside the context window; this module's attacks and defenses extend into the persistent surface.
**Reading the diagram**: Two horizontal bands. The top (long-term memory) is durable — it survives the session boundary. The bottom (context window) is ephemeral — it dies when the session ends. The arrow between them is the memory load that happens at session start, *before* the user types anything. Note that B2's layers all sit inside the context window and never touch the load path.
```mermaid
flowchart LR
subgraph LTM["LONG-TERM MEMORY — persists across sessions"]
direction TB
L1["stored OUTSIDE the model<br/>DB · vector store · KV cache · files"]
L2["survives logout / login / refresh<br/>version bump / session timeout"]
L3["loaded into context at session START<br/>before the user types anything"]
end
subgraph CW["CONTEXT WINDOW — per-session"]
direction TB
C1["system prompt · conversation history<br/>retrieved context · tool outputs (this turn)"]
C2["born at session start<br/>DIES at session end"]
C3["B2's 5 layers operate HERE<br/>tag · isolate · taint · gate · minimize"]
end
LTM ===|"memory load<br/>at session start<br/>(trusted by default)"| CW
style LTM fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#e4e4e8
style CW fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
style L1 fill:#101018,stroke:#f08080,color:#e4e4e8
style L2 fill:#101018,stroke:#f08080,color:#e4e4e8
style L3 fill:#101018,stroke:#f08080,color:#e4e4e8
style C1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C2 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C3 fill:#101018,stroke:#5eead4,color:#e4e4e8
```
> **Note**: The asymmetry is the point. Everything B2 defends is inside the context window and dies with the session. Long-term memory survives — and because it is loaded as trusted by default, a poisoned entry routes around all five B2 layers. B3 extends the defense into the persistent surface.
---
## Diagram 2 — The Sleeper Attack Across Sessions
**Type**: Timeline / sequence
**Purpose**: The centerpiece attack of the module, made visual. The sleeper attack (Course 1 Module 4.3): inject in session 1, the payload sleeps in memory, it activates in session 2. The fuse crosses the session boundary. The critical failure is not the injection in session 1 — it is the **unvalidated read in session 2**, where the memory loader promotes a poisoned entry to trusted context without re-checking it.
**Reading the diagram**: Two sessions separated by the session boundary (the fuse). In session 1 the seed is planted and is inert. Persistence carries it across. In session 2 the seed loads as trusted and fires. The red callout marks the load-bearing failure: the read path trusts the write path unconditionally.
```mermaid
flowchart TB
subgraph S1["SESSION 1 — THE INJECTION"]
direction TB
A1["attacker delivers payload"]
A2["agent writes SEED to memory<br/>(via save_to_memory, or ingest, or summary)"]
A3["seed is INERT this session<br/>nothing visible happens"]
A1 --> A2 --> A3
end
BOUND["SESSION BOUNDARY — THE FUSE<br/>logout · login · days pass<br/>user forgets session 1"]:::warn
subgraph S2["SESSION 2 — THE ACTIVATION"]
direction TB
B1["user starts fresh session"]
B2["memory loader runs<br/>pulls seed into context as TRUSTED"]
B3["no tag (B2 L1 missed it)<br/>no gate (B2 L3 missed it)<br/>seed is already in the window"]
B4["SEED FIRES<br/>agent obeys as if system prompt"]
B1 --> B2 --> B3 --> B4
end
FAIL["THE LOAD-BEARING FAILURE<br/>unvalidated READ in session 2<br/>memory trusted by default<br/>nothing re-checks the seed"]:::danger
S1 --> BOUND --> S2
B2 -. fails here .-> FAIL
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style S1 fill:#14141f,stroke:#f0a868,color:#e4e4e8
style S2 fill:#14141f,stroke:#f08080,color:#e4e4e8
style A1 fill:#101018,stroke:#f0a868,color:#e4e4e8
style A2 fill:#101018,stroke:#f0a868,color:#e4e4e8
style A3 fill:#101018,stroke:#f0a868,color:#e4e4e8
style B1 fill:#101018,stroke:#f08080,color:#e4e4e8
style B2 fill:#101018,stroke:#f08080,color:#e4e4e8
style B3 fill:#101018,stroke:#f08080,color:#e4e4e8
style B4 fill:#101018,stroke:#f08080,stroke-width:1.5px,color:#f08080
```
> **Note**: The two events may be days apart, in different contexts, under different account states — which makes the sleeper attack harder to attribute than a same-session injection. By the time it fires, the trail back to session 1 is cold. The defense (B3.3) does not try to catch the injection in session 1; it ensures the seed can never be written, and that any residual poison is tagged on read.
---
## Diagram 3 — Retrieval Contamination Flow
**Type**: Data-flow / pipeline
**Purpose**: How a poisoned chunk travels from a writable source through the retrieval store into the context window. The retrieval store is written by many paths (user uploads, crawled content, agent summaries, cross-tenant leaks) — not all trusted. Once a poisoned chunk is in the index, retrieval is the activation mechanism: the attacker crafts the chunk to be semantically similar to the victim's queries, so the poison is fetched, inserted as data-but-obeyed-as-instruction, and the agent complies. This is indirect injection (B2's most dangerous class) with the persistence property of memory.
**Reading the diagram**: Left to right — the write paths into the index (red = untrusted), the poisoned chunk persisting, the retrieval fetching it on a relevant query, and the injection into the context window. The green callout marks the defense: retrieved-content taint tagging (B2 Layer 1) connects B3 retrieval defense to the B2 stack.
```mermaid
flowchart LR
subgraph WRITE["WRITE PATHS INTO THE INDEX"]
direction TB
W1["user-uploaded doc"]:::danger
W2["crawled / synced content<br/>(compromised wiki page)"]:::danger
W3["agent-generated summary<br/>(laundered injection)"]:::danger
W4["cross-tenant leak<br/>(weak isolation)"]:::danger
end
IDX[("RETRIEVAL STORE<br/>vector / keyword index<br/>PERSISTS — poison stays<br/>until found + removed")]:::warn
subgraph RETRIEVE["RETRIEVAL — THE ACTIVATION"]
direction TB
R1["victim issues a query"]
R2["poisoned chunk is semantically similar<br/>→ it is FETCHED"]
R3["chunk inserted into context window<br/>as DATA — but obeyed as INSTRUCTION"]
R1 --> R2 --> R3
end
DEF["DEFENSE — taint tagging<br/>retrieved chunk tagged UNTRUSTED (B2 L1)<br/>taint gate (B2 L3) blocks high-impact calls<br/>provenance filtering + re-ranking upstream"]:::good
WRITE --> IDX
IDX --> RETRIEVE
R3 -. defended by .-> DEF
classDef danger fill:#101018,stroke:#f08080,color:#e4e4e8
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style W1 fill:#101018,stroke:#f08080,color:#e4e4e8
style W2 fill:#101018,stroke:#f08080,color:#e4e4e8
style W3 fill:#101018,stroke:#f08080,color:#e4e4e8
style W4 fill:#101018,stroke:#f08080,color:#e4e4e8
style IDX fill:#14141f,stroke:#f0a868,stroke-width:2px,color:#f0a868
style R1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style R2 fill:#101018,stroke:#f08080,color:#e4e4e8
style R3 fill:#101018,stroke:#f08080,stroke-width:1.5px,color:#f08080
```
> **Note**: The retrieval store is a memory surface, and it is the most commonly writable one — ingestion pipelines (sync, crawl, bulk import) may bypass the model-propose/harness-validate gate entirely. The defense is not to make the store unwritable; it is to treat every retrieved chunk as untrusted by default (B2 Layer 1) unless its provenance proves otherwise, so the taint gate applies.
---
## Diagram 4 — The Harness-Managed-Write Gate
**Type**: Process / control flow
**Purpose**: The central defense of the module, made visual. The model PROPOSES memory writes; the harness VALIDATES them; only the harness COMMITS. Three checks in order — provenance (where did it come from), trust level (is the source trusted), content (does it look like an injection). The conjunction of *untrusted provenance AND instruction-like content* is the sleeper-attack signature that CHECK 3 blocks deterministically. The model never touches the store directly.
**Reading the diagram**: The model emits a proposal (content + justification + provenance). The gate runs three checks. Any failure → DENY (logged, surfaced). All pass → COMMIT with provenance + trust + decision tag. The unconditional write path (the `save_to_memory` tool) does not exist.
```mermaid
flowchart TB
PROP["MODEL PROPOSES a write<br/>content + justification + provenance<br/>(the model NEVER touches the store)"]:::accent
GATE["HARNESS VALIDATION GATE<br/>three checks, in order"]
C1["CHECK 1 — PROVENANCE<br/>where did the content come from?<br/>user_direct · retrieval · tool · agent_inferred"]:::check
C2["CHECK 2 — TRUST LEVEL<br/>trusted · semi_trusted · untrusted<br/>(derived from provenance)"]:::check
C3["CHECK 3 — CONTENT<br/>does it look like an injection?<br/>detector + sleeper-signature heuristic"]:::check
DENY["DENY — log + surface<br/>injection_detected · untrusted_instruction_like<br/>· provenance_violation"]:::danger
COMMIT["COMMIT — only the harness writes<br/>entry tagged: source + trust_level<br/>+ timestamp + writer + validation_result"]:::good
READ["READ PATH (separate)<br/>load entry → tag by trust level<br/>untrusted entries get B2 L1 tag<br/>→ taint gate applies on next session"]:::check
PROP --> GATE
GATE --> C1 --> C2 --> C3
C1 -. fail .-> DENY
C2 -. untrusted + instruction-like .-> DENY
C3 -. fail .-> DENY
C3 -. all pass .-> COMMIT
COMMIT -. read later .-> READ
classDef accent fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
classDef check fill:#101018,stroke:#5eead4,color:#e4e4e8
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style GATE fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
style PROP fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
style C1 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C2 fill:#101018,stroke:#5eead4,color:#e4e4e8
style C3 fill:#101018,stroke:#5eead4,color:#e4e4e8
style DENY fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style COMMIT fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
style READ fill:#101018,stroke:#f0a868,color:#e4e4e8
```
> **Note**: The load-bearing line is CHECK 3's conjunction: `if (trustLevel === "untrusted" && looksLikeInstruction(...))`. A trusted user directly stating a preference passes. An untrusted chunk that happens to be factual passes. The conjunction catches the payload that is *both* untrusted-sourced and instruction-shaped — which is exactly what a sleeper seed is. The gate's strength is not perfection; it is the removal of the unconditional write path.
---
## Diagram 5 — Cascading Hallucination (ASI06)
**Type**: Propagation / cascade
**Purpose**: Why a single poisoned or hallucinated result is worse than a localized error — the downstream risk OWASP ranks as ASI06. The agent retrieves or recalls one false premise, treats it as ground truth, and builds all subsequent reasoning on top of it. The error propagates through the chain: false premise → flawed reasoning → flawed action → recorded result → further reasoning. By the time the user sees the output, the original error is buried under layers of plausible derivation, and if the premise was persisted to memory, the cascade recurs every session.
**Reading the diagram**: Top to bottom — the cascade. The poison enters (from memory or retrieval), becomes a premise, drives reasoning, drives an action, the action's result is recorded, and further reasoning builds on it. Each step inherits the original error. The amber callout marks the source: poisoned memory is the most reliable cascade trigger, because the agent treats its own memory as authoritative.
```mermaid
flowchart TB
SRC["POISONED / HALLUCINATED PREMISE<br/>from memory (ASI04) or retrieval (RAG poison)"]:::danger
P1["agent treats premise as GROUND TRUTH<br/>(memory = authoritative; retrieval = data-but-obeyed)"]:::danger
R1["agent REASONS on the false premise"]
ACT["agent takes an ACTION<br/>calls a tool · generates output<br/>based on the flawed reasoning"]
REC["action result is RECORDED<br/>(to memory · to context · to a log)"]
R2["agent reasons FURTHER<br/>on top of the recorded result"]
OUT["USER SEES THE OUTPUT<br/>internally consistent chain<br/>but the FOUNDATION was poisoned"]:::warn
CASCADE["THE CASCADE<br/>every downstream step inherits<br/>the original error<br/>the longer it runs, the deeper it buries"]:::danger
SRC --> P1 --> R1 --> ACT --> REC --> R2 --> OUT
R2 -. loop .-> R1
P1 -. drives .-> CASCADE
classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
style SRC fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
style P1 fill:#101018,stroke:#f08080,color:#f08080
style R1 fill:#101018,stroke:#f08080,color:#e4e4e8
style ACT fill:#101018,stroke:#f08080,color:#e4e4e8
style REC fill:#101018,stroke:#f0a868,color:#e4e4e8
style R2 fill:#101018,stroke:#f08080,color:#e4e4e8
style OUT fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#f0a868
style CASCADE fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
```
> **Note**: A single hallucination is a localized error the user corrects. A cascading hallucination is a contaminated reasoning chain — and the cascade is faster and harder to interrupt when the foundation is the agent's own prior memory. The defense is not to catch each hallucination individually; it is to prevent poisoned premises from entering memory (B3.3 gate) and to detect propagation when it starts (audit the reasoning chain, purge the poisoned premise from the store).