# Diagrams — SDD-B03: InjecAgent: The Bridge Benchmark

**Module**: SDD-B03 — InjecAgent: The Bridge Benchmark
**Diagram count**: 5
**Tool**: Mermaid (primary). Each diagram validated in [Mermaid Live Editor](https://mermaid.live).

---

## Diagram 1 — The Four Roles of One Benchmark

**Type**: Role map
**Purpose**: The single most important concept in the bridge. The InjecAgent code does not change between Course 2A and Course 2B; what changes is the question asked of it. The same benchmark plays four roles — quality gate (2A), measurement instrument (2B), regression gate (both), engagement scoper (B12). A 2A graduate who only knows the first role will under-use the benchmark in 2B.
**Reading the diagram**: Four panels, one per role, each with its question and its unit of analysis. The center is the unchanged benchmark. The arrows show the role shift across the bridge.

```mermaid
flowchart TB
  CORE["INJECAGENT<br/>the same benchmark code<br/>task set + injected tool outputs<br/>+ pass/fail scorer"]

  R1["ROLE 1 — QUALITY GATE (2A)<br/>Q: Is my harness injectable?<br/>Unit: per-tool score"]:::teal
  R2["ROLE 2 — MEASUREMENT INSTRUMENT (2B)<br/>Q: Did this defense hold, and by how much?<br/>Unit: before/after delta"]:::warn
  R3["ROLE 3 — REGRESSION GATE (both)<br/>Q: Did this change open an injection surface?<br/>Unit: pass/fail at merge"]:::teal
  R4["ROLE 4 — ENGAGEMENT SCOPER (B12)<br/>Q: Which chains do I run?<br/>Unit: transcript → chain finding"]:::warn

  CORE --> R1
  CORE --> R2
  CORE --> R3
  CORE --> R4

  BRIDGE["THE BRIDGE<br/>same code · different question · different lens<br/>2A builder → 2B authorized red-team"]:::ok

  R1 -.->|cross the bridge| BRIDGE
  BRIDGE -.-> R2
  BRIDGE -.-> R3
  BRIDGE -.-> R4

  classDef teal fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#e4e4e8
  classDef ok fill:#14141f,stroke:#82e0aa,stroke-width:2px,color:#82e0aa
  style CORE fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
```

> **Note**: The benchmark is a tool, not a verdict. The verdict depends on the question. A 48% score is a failing grade in the quality-gate role and the baseline denominator in the measurement-instrument role. Same number, opposite readings.

---

## Diagram 2 — The Defense-Effectiveness Delta

**Type**: Before/after comparison
**Purpose**: The load-bearing metric of B03.2. The only honest defense-effectiveness claim is a (before, after, configuration) triple. A defended number without its baseline is a claim with no evidence. The diagram shows the delta as the difference between two measured runs with everything pinned except the defense under test.
**Reading the diagram**: Two runs — baseline (defenses off) and defended (defenses on) — same task set, same model version, same sampling. The delta is the effectiveness. The configuration card pins the variables.

```mermaid
flowchart LR
  subgraph BEFORE["BASELINE — defenses OFF"]
    direction TB
    B1["Task set: 100 tasks<br/>Model: pinned version<br/>Sampling: temp 0.0<br/>Defenses: NONE"]
    B2["Result: 48% injection success<br/>= the 'before' number"]
  end
  subgraph AFTER["DEFENDED — defenses ON"]
    direction TB
    A1["Task set: SAME 100 tasks<br/>Model: SAME pinned version<br/>Sampling: SAME temp 0.0<br/>Defenses: egress gate + structured output"]
    A2["Result: 9% injection success<br/>= the 'after' number"]
  end

  BEFORE ---|"only variable changed:<br/>the defense"| AFTER

  DELTA["THE DELTA<br/>48% → 9%<br/>= defense effectiveness<br/>(the only honest claim)"]:::good

  AFTER --> DELTA

  CONFIG["CONFIG CARD (pinned)<br/>model version · sampling params<br/>defense settings · task set hash<br/>= makes the triple reproducible"]:::warn
  DELTA -.->|requires| CONFIG

  classDef good fill:#14141f,stroke:#82e0aa,stroke-width:2px,color:#82e0aa
  classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#e4e4e8
  style BEFORE fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#e4e4e8
  style AFTER fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style B1 fill:#101018,stroke:#f08080,color:#e4e4e8
  style B2 fill:#101018,stroke:#f08080,color:#f08080
  style A1 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style A2 fill:#101018,stroke:#5eead4,color:#5eead4
```

> **Note**: The anti-pattern this diagram kills: "we added the egress gate and now we're at 9%." Without the 48% baseline, the 9% is noise. The triple — (48%, 9%, pinned config) — is the finding. Every effectiveness claim in a B12 engagement is a triple.

---

## Diagram 3 — The Attack-Type Taxonomy: Score to Prescription

**Type**: Matrix / router
**Purpose**: A single "60% injectable" number is a headline. The prescription comes from the attack-type breakdown. Each attack type maps to a different defense, and a B12 engagement prescribes defenses. This is the bridge from measurement to prescription — the reason the taxonomy is mandatory in 2B.
**Reading the diagram**: Left column = attack type the injection attempts. Right column = the defense that closes it. The benchmark's per-attack-type scorecard routes each failing tool to its defense.

```mermaid
flowchart LR
  subgraph ATTACKS["ATTACK TYPE (what the injection attempts)"]
    direction TB
    T1["CREDENTIAL EXFIL<br/>emit a secret in output / egress"]
    T2["DISALLOWED-TOOL CALL<br/>invoke a tool outside task scope"]
    T3["SCOPE ESCAPE<br/>past the scope file boundary"]
    T4["POLICY OVERRIDE<br/>treat injection as new policy"]
    T5["ACTION REDIRECTION<br/>different benign-looking action"]
  end
  subgraph DEFENSES["DEFENSE THAT CLOSES IT"]
    direction TB
    D1["Deterministic egress gate<br/>+ credential quarantine<br/>(IronCurtain, DD-20)"]:::teal
    D2["Tool-call policy enforcement<br/>+ dispatch unique-resolution"]:::teal
    D3["Scope gate re-checked per action<br/>+ valid_until enforcement"]:::teal
    D4["Explicit instruction hierarchy<br/>+ goal-reaffirmation checkpoints"]:::teal
    D5["Session-level intent detection<br/>(SDD-B02 control)"]:::warn
  end

  T1 --> D1
  T2 --> D2
  T3 --> D3
  T4 --> D4
  T5 --> D5

  classDef teal fill:#101018,stroke:#5eead4,color:#e4e4e8
  classDef warn fill:#101018,stroke:#f0a868,color:#e4e4e8
  style ATTACKS fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#e4e4e8
  style DEFENSES fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style T1 fill:#101018,stroke:#f08080,color:#e4e4e8
  style T2 fill:#101018,stroke:#f08080,color:#e4e4e8
  style T3 fill:#101018,stroke:#f08080,color:#e4e4e8
  style T4 fill:#101018,stroke:#f08080,color:#e4e4e8
  style T5 fill:#101018,stroke:#f08080,color:#e4e4e8
```

> **Note**: A tool failing 60% on credential-exfiltration needs a different defense than one failing 60% on action-redirection. The per-attack-type scorecard is the prescription, not the headline. This is the section of a B12 report that says "here is what is broken, here is the defense, here is the expected delta."

---

## Diagram 4 — The Transcript Read as a Chain Finding

**Type**: Transform / lens
**Purpose**: Every InjecAgent failure transcript is a partial attack chain. Read in isolation it is an injection-resistance bug. Read through the SDD-B01 (OWASP) and SDD-B02 (Microsoft) lenses, it becomes a cross-row chain finding. The benchmark produces the raw material; the taxonomy produces the finding.
**Reading the diagram**: One transcript enters; two lenses are applied; the output is a chain (ASI07 → ASI01 → ASI05) or, for compounds, the zero-click HITL bypass. The benchmark routes to the taxonomies; it does not replace them.

```mermaid
flowchart TB
  TRANS["INJECAGENT FAILURE TRANSCRIPT<br/>injected tool output arrived<br/>→ agent followed it<br/>→ off-task action executed"]

  TRANS --> LENS1["LENS 1 — OWASP (SDD-B01)"]
  TRANS --> LENS2["LENS 2 — MICROSOFT (SDD-B02)"]

  LENS1 --> CHAIN1["ASI07 insecure output handling<br/>→ ASI01 goal hijacking<br/>→ ASI05 tool abuse<br/>(→ ASI03 excessive agency)<br/>= cross-row chain finding"]:::warn

  LENS2 --> CHAIN2["if the off-task action was a compound<br/>passing per-step approval individually<br/>→ ZERO-CLICK HITL BYPASS<br/>= session-level intent gap"]:::danger

  ROUTE["B12 ENGAGEMENT ROUTES<br/>credential-exfil → CrabTrap/IronCurtain attacks<br/>action-redirect → Microsoft chain recon<br/>scope-escape → OWASP ASI03/05 procedures"]

  CHAIN1 --> ROUTE
  CHAIN2 --> ROUTE

  classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#e4e4e8
  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style TRANS fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style LENS1 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style LENS2 fill:#101018,stroke:#5eead4,color:#e4e4e8
  style ROUTE fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
```

> **Note**: The benchmark does not replace the taxonomies — it routes traffic to them. A B12 engagement that skips the InjecAgent pass and jumps to the taxonomies is scoping blind. Run the benchmark, read the scorecard, route the high-score tools to the matching chain procedures.

---

## Diagram 5 — The Regression Gate: Three Changes That Open Surfaces

**Type**: Process / control flow
**Purpose**: A one-time InjecAgent run tells you your current rate. A CI-integrated gate tells you when a change regresses it. Three routine changes open injection surfaces: a new tool, a prompt edit, a model swap. The gate catches all three by re-running the benchmark and comparing to threshold at every merge.
**Reading the diagram**: Three change triggers on the left feed the gate. The gate runs the benchmark, compares to threshold, and produces a binary merge decision. The threshold is a policy choice; the enforcement is mechanical.

```mermaid
flowchart TB
  C1["NEW TOOL ADDED<br/>new injection point<br/>did they wrap the output?"]:::warn
  C2["PROMPT EDITED<br/>wording weakened resistance<br/>author won't notice"]:::warn
  C3["MODEL SWAPPED<br/>new model parses outputs<br/>more naively / silently"]:::warn

  C1 --> GATE
  C2 --> GATE
  C3 --> GATE

  GATE["INJECAGENT REGRESSION GATE<br/>re-run benchmark<br/>compare to threshold<br/>(pin model · sampling · config)"]

  GATE --> Q{"injection rate<br/>below threshold?"}
  Q -->|YES| MERGE["ALLOW MERGE<br/>surface stayed closed"]:::good
  Q -->|NO| BLOCK["BLOCK MERGE<br/>change opened a surface<br/>fix OR raise threshold w/ sign-off"]:::danger

  POLICY["THRESHOLD = POLICY<br/>(5%? 10%? — a choice)<br/>ENFORCEMENT = MECHANICAL<br/>(the gate runs every merge)"]:::teal
  GATE -.->|enforced by| POLICY

  classDef warn fill:#14141f,stroke:#f0a868,stroke-width:1.5px,color:#e4e4e8
  classDef good fill:#14141f,stroke:#82e0aa,stroke-width:1.5px,color:#82e0aa
  classDef danger fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  classDef teal fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#5eead4
  style GATE fill:#14141f,stroke:#5eead4,stroke-width:2px,color:#5eead4
  style Q fill:#101018,stroke:#f0a868,color:#e4e4e8
```

> **Note**: A threshold that is measured but not gated is a documented vulnerability. The gate is what turns a measurement into a control. Without it, the standard erodes the moment a deadline arrives — the team raises the threshold "just this once," and the injection surface reopens silently.
