Observability and Attack Detection

Module B8 · Course 2B — Securing & Attacking Harnesses and LLMs

60 minutes · Per-turn detection is necessary but insufficient — the attacks that actually compromise agents are invisible to a system that inspects each turn independently

The unit of malicious intent is the session, not the turn. Each step looks benign; the compound intent is malicious. Detection must move to the session.

Pillar 3 — Controls

The inversion from Course 1 Module 10

Course 1 Module 10 taught you to observe an honest agent. B8 teaches you what the observability pipeline must look for when an adversary is steering it.

Course 1 Module 10 — observability

Question: "is the agent working?" — performance, correctness, latency. Structured logs, traces, replay. The plumbing.

B8 — adversarial detection

Question: "is the agent being steered?" — adversarial drift, anomaly, chain. Additional detectors on the same plumbing.

The two attacks per-turn detection misses

1. The multi-step injection (B2). Four benign-looking turns — summarize → translate → email → "also attach ~/.ssh/id_rsa" — compound to a private-key exfiltration. Each turn passes a per-turn detector.
2. The zero-click HITL bypass chain (Microsoft Taxonomy v2.0). A single external input triggers a chain where every step passes a human approval, yet the compound intent is malicious. Per-step approval is the control being defeated.
The shared property: malicious intent distributed across individually-benign units. A per-turn detector sees benign atoms. The molecule is poison.

Per-turn: necessary but insufficient

ScopeCatchesMisses
Per-turnSingle-shot injections, obvious policy violations, leakage in one outputMulti-step chains, zero-click chains, cascading corruption
Session-levelAction drift from objective, chain composition, untrusted-source high-drift steps(nothing — it subsumes the per-turn signal when combined)
You need both. Drop per-turn and you lose the long tail of single-shot attacks. Keep only per-turn and you have no coverage on the chains that exfiltrate the key, drain the account, or pivot into a forbidden tool.

B8.1 — Why per-turn detection fails

The multi-step chain and the zero-click HITL bypass

The zero-click HITL bypass chain

ONE external input (email / page / retrieved doc / MCP resp.)
   carries an indirect injection
        │
        ▼
   STEP 1  read /app/.env            ✓ approved (looks routine)
   STEP 2  PATCH /billing/method     ✓ approved (looks routine)
   STEP 3  draft email → attacker@   ✓ approved (looks routine)
   STEP 4  SEND                      ✓ approved (looks routine)
        │
        ▼
   COMPOUND: credential exfiltrated · payment swapped · irreversible

   PER-STEP APPROVAL: 4 of 4 passed. The human never saw the chain.
The Microsoft Taxonomy's critical finding. Per-step HITL is the control being defeated. The human is not bypassed in any single step — they are composed across steps. Defense requires a session-level model of intent.

ASI06: Cascading Hallucination as a detection target

OWASP ASI06 names the unintentional twin of the multi-step injection: an early error or compromise propagates through subsequent steps, compounding into a confidently-corrupted downstream action.
One signal, two failure modes. A detector built only to catch injection misses the cascading-hallucination version of the same drift. A session-level intent tracker catches both for the price of one — the signal is "the agent's actions have drifted from a coherent objective," regardless of whether the cause is adversarial or accidental.

B8.2 — Session-level intent tracking & provenance

The detection counterpart to B2's session-level defense

The session intent model

Deterministic skeleton (immune to injection)
Seeded from system prompt + first user turn. Updated ONLY from trusted sources. Carries resource scope, egress policy, task class.
Constrained LLM update layer
Proposes semantic updates ("user switched to Q4"). Bounded to ≤0.2 of drift score — cannot single-handedly flip a decision.
The three-outcome drift gate. High drift + untrusted source → HARD BLOCK. High drift + trusted source → REQUIRE FRESH APPROVAL (show the drift reason). Low drift → ALLOW. The HARD BLOCK on untrusted-source high-drift is the move that catches the zero-click chain at its exfiltration step.

Action provenance: "which input caused this?"

FieldWhy it matters
source_typeuser_turn · system_prompt · tool_output · retrieved_chunk · mcp_response
source_idPointer to the specific input that caused the action (turn N, chunk K)
source_trusttrusted (user/system) vs. untrusted (retrieval/tool/MCP) — weights the drift signal
intent_drift_scoreThe drift score at decision time — forensic + detection input
Capture at prompt-assembly time. A harness that pipes an undifferentiated context blob into the model throws provenance away at the moment of capture. No after-the-fact log analysis recovers it. Tag every context item with a stable source identity and trust level when assembling the prompt.

B8.3 — Anomaly, approval freshness, the stack

Statistical baselines, defeating fatigue, assembling the whole

Anomaly detection: drift is local, anomaly is global

BaselineSignal
Action frequencyBursts — a chain executing its payload before the human notices
Tool-call distributionRead-heavy agent suddenly spikes writes/sends; code agent sends external email
Parameter distributionsRead of ~/.ssh/* when baseline is /reports/*; external domain when baseline is internal
Sequence patterns"read_secret → encode → send_external" transitions; sensitive-then-egress
Catches the attack you did not write a rule for. Drift = "doesn't fit the session." Anomaly = "doesn't fit the agent." Adversaries rotate; you need both. ← Consumes B7's sidecar signals (resource / syscall / net / behavioral) — correlated on timestamp.

Approval freshness: defeat escalation fatigue

DD-20 IronCurtain. Flood the human with approval requests at machine speed until they rubber-stamp. Volume defeats vigilance.
DefenseDefeats
Rate limits — surplus requests AUTO-BLOCKEDThe volume attack
Batch approvals — show the CHAIN as one reviewed objectPer-step composition (makes compound intent visible)
Freshness windows — approval valid N seconds onlyApproval harvesting / harvest-and-replay
None alone is sufficient. Rate limits without batching still let a chain walk through one-at-a-time. Batching without freshness allows replay. Freshness without rate limits does nothing about a single fast chain. The approval UX shows drift + anomaly + chain — not "approve Y/N" for an isolated step.

The observability stack, assembled

1. STRUCTURED ACTION LOG (every action, with provenance)
     → audit trail; feeds anomaly detection
2. SESSION INTENT TRACKER      → drift gate (B8.2)
3. ANOMALY DETECTOR            → deviation gate (B8.3)
     ← consumes B7 sidecar (resource/syscall/net/behavioral)
4. APPROVAL GATE WITH FRESHNESS → defeats fatigue (DD-20)
5. HUMAN-REVIEWABLE AUDIT TRAIL → replay any session w/ provenance
     → ties to Course 1 M10 (Observability) + M9 (Verification)
The load-bearing principle. Course 1 Module 10's plumbing, plus the adversarial detectors this module adds. Verification (M9) with the provenance log becomes an audit, not a guess — every action's source is known, every drift score recorded.

Lab & what's next

Lab (07): build the Session-Level Detector — a SessionIntentTracker with deterministic skeleton + constrained LLM + three-outcome drift gate; an ActionProvenanceLogger tagging source/trust at capture time; an AnomalyDetector with frequency/tool/parameter baselines. Climax: a zero-click chain replay — five benign-looking steps that compound to a malicious outcome — where the per-turn detector passes every step and the session-level detector fires on the chain.

Next — B9: OWASP Agentic Top 10 as Engineering Checklist. B9 takes the ASI entries (including ASI06, mapped here) and turns them into a reviewable engineering checklist that ties every module from B1–B8 to a concrete control.