Module: SDD-B03 — InjecAgent: The Bridge Benchmark Diagram count: 5 Tool: Mermaid (primary). Each diagram validated in Mermaid Live Editor.
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.
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.
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.
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.
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.
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."
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.
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.
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.
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.
# 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.