# Diagrams — Module S02: Bug Bounty Harness Engineering

> All Mermaid validated in Mermaid Live Editor. n8n JSON is structurally valid and importable.

---

## Diagram 1 — The Bug Bounty Harness Architecture (n8n)

**Type**: n8n workflow (importable JSON)
**Purpose**: The primary visual — the full bug bounty harness as a node graph. Shows the four tiers (recon, webapp, evidence, report) connected by the scope enforcement middleware and engagement memory.

```json
{
  "name": "S02 — Bug Bounty Harness Architecture",
  "nodes": [
    { "name": "Engagement Start", "type": "n8n-nodes-base.manualTrigger", "position": [200, 300], "notes": "Operator initiates with scope.json loaded" },
    { "name": "Load Scope File", "type": "n8n-nodes-base.set", "position": [400, 300], "notes": "scope.json → middleware. valid_until checked." },
    { "name": "Recon: Subdomain Enum", "type": "n8n-nodes-base.executeCommand", "position": [620, 200], "notes": "amass/subfinder → discovered subdomains" },
    { "name": "Recon: Port Scan", "type": "n8n-nodes-base.executeCommand", "position": [620, 300], "notes": "nmap → open ports, services" },
    { "name": "Recon: HTTP Probe", "type": "n8n-nodes-base.executeCommand", "position": [620, 400], "notes": "httpx → live HTTP services" },
    { "name": "Scope Middleware (ALL calls)", "type": "n8n-nodes-base.set", "position": [840, 300], "notes": "Intercepts every outbound call. Target in scope? Action permitted? Fresh scope? → stamp scope_ref" },
    { "name": "Engagement Memory (ChromaDB)", "type": "n8n-nodes-base.set", "position": [1060, 300], "notes": "Persistent store: subdomains, ports, services, hypotheses. Dedup at write time." },
    { "name": "Vuln Scan: nuclei", "type": "n8n-nodes-base.executeCommand", "position": [1280, 200], "notes": "Template-based scanning → raw findings" },
    { "name": "Web: ffuf/sqlmap", "type": "n8n-nodes-base.executeCommand", "position": [1280, 300], "notes": "Directory brute, SQLi test → raw findings" },
    { "name": "Triage Pipeline", "type": "n8n-nodes-base.set", "position": [1500, 300], "notes": "Dedup → severity → enrich → model-judged triage → surface/batch/discard" },
    { "name": "Evidence Logger", "type": "n8n-nodes-base.set", "position": [1500, 450], "notes": "Hash-chained, append-only, scope-referenced. Every call auto-logged." },
    { "name": "Report Generator", "type": "n8n-nodes-base.set", "position": [1720, 300], "notes": "Structured findings → HTML/JSON report with CVSS, evidence, remediation" }
  ],
  "connections": {
    "Engagement Start": { "main": [[{ "node": "Load Scope File", "type": "main", "index": 0 }]] },
    "Load Scope File": { "main": [[{ "node": "Recon: Subdomain Enum", "type": "main", "index": 0 }]] },
    "Recon: Subdomain Enum": { "main": [[{ "node": "Scope Middleware (ALL calls)", "type": "main", "index": 0 }]] },
    "Recon: Port Scan": { "main": [[{ "node": "Scope Middleware (ALL calls)", "type": "main", "index": 0 }]] },
    "Recon: HTTP Probe": { "main": [[{ "node": "Scope Middleware (ALL calls)", "type": "main", "index": 0 }]] },
    "Scope Middleware (ALL calls)": { "main": [[{ "node": "Engagement Memory (ChromaDB)", "type": "main", "index": 0 }]] },
    "Engagement Memory (ChromaDB)": { "main": [[{ "node": "Vuln Scan: nuclei", "type": "main", "index": 0 }], [{ "node": "Web: ffuf/sqlmap", "type": "main", "index": 0 }]] },
    "Vuln Scan: nuclei": { "main": [[{ "node": "Triage Pipeline", "type": "main", "index": 0 }]] },
    "Web: ffuf/sqlmap": { "main": [[{ "node": "Triage Pipeline", "type": "main", "index": 0 }]] },
    "Triage Pipeline": { "main": [[{ "node": "Report Generator", "type": "main", "index": 0 }]] },
    "Scope Middleware (ALL calls)": { "main": [[{ "node": "Evidence Logger", "type": "main", "index": 0 }]] }
  }
}
```

**Reading the diagram**: Left to right. Scope file loads into the middleware that intercepts ALL outbound calls. Recon tools (amass, nmap, httpx) discover the attack surface; results pass through scope middleware into engagement memory (ChromaDB). From memory, the harness launches vulnerability scanning (nuclei) and web testing (ffuf, sqlmap). All raw findings flow through the triage pipeline. Every call — recon, scanning, testing — is auto-logged to the evidence logger with scope_ref. Triaged findings become the report. The engagement memory persists across sessions; the evidence log persists for legal protection.

---

## Diagram 2 — The Engagement Memory Write Path (dedup at write time)

**Type**: Mermaid (flowchart)
**Purpose**: Shows how memory avoids the accumulation problem — every write is checked against existing records.

```mermaid
flowchart TD
    TOOL["Tool output<br/>(e.g., nmap found port 443)"]
    PARSE["Parse to structured record"]
    DEDUP{"Duplicate in<br/>memory?"}
    UPDATE["Update existing record<br/>(last_seen, merge data)"]
    INSERT["Insert new record<br/>(assign UUID)"]
    MEM["Engagement Memory<br/>(ChromaDB)"]

    TOOL --> PARSE --> DEDUP
    DEDUP -->|"yes, same target+port"| UPDATE --> MEM
    DEDUP -->|"no"| INSERT --> MEM

    POISON{"Raw response<br/>contains injection?"}
    POISON -->|"if written verbatim"| CORRUPT["Memory corrupted<br/>across sessions"]
    POISON -->|"defense: structured summary only"| SAFE["Only structured data written<br/>injection cannot inject records"]

    style DEDUP fill:#14141f,stroke:#5eead4,color:#5eead4
    style CORRUPT fill:#2a0d0d,stroke:#a00000,color:#f08080
    style SAFE fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style MEM fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
```

**Reading the diagram**: Every tool output is parsed to a structured record, then checked against existing memory. Duplicates update the existing record (refreshing last_seen, merging new data); unique records are inserted. This keeps memory clean — it grows with unique knowledge, not raw output volume. The lower section shows the memory poisoning defense: raw responses that may contain injection are never written verbatim; only structured summaries (from the Reader Model per S01.3) enter the store.

---

## Diagram 3 — The Harness Tool Wrapping Pattern

**Type**: Mermaid (flowchart)
**Purpose**: Every offensive tool follows this same wrapping pattern. Shows the layers between the model's request and the network.

```mermaid
flowchart LR
    MODEL["Model emits<br/>tool_use"]
    SCHEMA["Pydantic schema<br/>validates input"]
    SCOPE["Scope check<br/>(belt + suspenders)"]
    RATE["Rate limiter<br/>(RoE caps)"]
    EXEC["Execute subprocess<br/>(nmap/nuclei/ffuf)"]
    PARSE["Parse output<br/>to structured result"]
    EVID["Evidence logger<br/>(scope_ref stamped)"]
    RESULT["Structured ToolResult<br/>→ model context"]

    MODEL --> SCHEMA --> SCOPE --> RATE --> EXEC --> PARSE --> EVID --> RESULT

    style MODEL fill:#14141f,stroke:#5eead4,color:#5eead4
    style SCOPE fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style EVID fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style EXEC fill:#2a1810,stroke:#a04000,color:#f0a868
```

**Reading the diagram**: Every offensive tool follows the same seven-step path. The model emits a tool_use with structured input. Pydantic validates the input. The scope check runs (belt-and-suspenders with the middleware). The rate limiter enforces RoE caps. The subprocess executes. Output is parsed to structured fields (raw output retained for evidence but not for model context). The evidence logger stamps scope_ref. The model sees the structured ToolResult — clean, typed, safe.

---

## Diagram 4 — The Evidence Chain (hash-linked, append-only)

**Type**: Mermaid (flowchart)
**Purpose**: The evidence log's structure. Each record is hash-linked to the previous, making tampering detectable.

```mermaid
flowchart LR
    R1["Record 1<br/>hash: abc123"]
    R2["Record 2<br/>prev: abc123<br/>hash: def456"]
    R3["Record 3<br/>prev: def456<br/>hash: ghi789"]
    R4["Record N<br/>prev: ghi789<br/>hash: ..."]

    R1 -.->|"hash chain"| R2
    R2 -.->|"hash chain"| R3
    R3 -.->|"hash chain"| R4

    TAMPER["Tamper with Record 2"]
    TAMPER -.->|"changes hash"| R2
    R2 -.->|"chain BROKEN<br/>at Record 3"| BROKEN["Tamper-evident<br/>detection"]

    style R1 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style R2 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style R3 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style R4 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style TAMPER fill:#2a0d0d,stroke:#a00000,color:#f08080
    style BROKEN fill:#2a0d0d,stroke:#a00000,color:#f08080
```

**Reading the diagram**: Each evidence record includes the hash of the previous record. Record 2's hash depends on Record 1's hash; Record 3's depends on Record 2's. Tampering with any record changes its hash, which breaks the chain at the next record — making tampering detectable. This is the tamper-evidence property: you cannot alter an evidence record without leaving a trace. The chain is append-only — no record is ever modified or deleted (destruction is batch-level per the retention policy, with the destruction itself recorded).

---

## Diagram 5 — The Triage Pipeline

**Type**: Mermaid (flowchart)
**Purpose**: The signal/noise filter. Raw scanner output → prioritized finding list. Shows where the model-judged triage sits.

```mermaid
flowchart TD
    RAW["Raw findings<br/>(e.g., 200 from nuclei)"]
    DEDUP["Dedup<br/>(against memory + known FPs)"]
    SEVERITY["Severity score<br/>(CVSS draft)"]
    ENRICH["Context enrichment<br/>(CVE, CWE, exploitability)"]
    TRIAGE["Model-judged triage<br/>(secondary LLM: exploitable? in scope? FP?)"]

    RAW --> DEDUP --> SEVERITY --> ENRICH --> TRIAGE

    TRIAGE -->|"critical/high, exploitable, in scope"| SURFACE["SURFACE<br/>notify operator now"]
    TRIAGE -->|"medium/low, needs verification"| BATCH["BATCH<br/>accumulate for report"]
    TRIAGE -->|"confirmed FP or out of scope"| DISCARD["DISCARD<br/>log but don't surface"]

    style RAW fill:#2a1810,stroke:#a04000,color:#f0a868
    style TRIAGE fill:#14141f,stroke:#5eead4,color:#5eead4
    style SURFACE fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style BATCH fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style DISCARD fill:#2a0d0d,stroke:#a00000,color:#f08080
```

**Reading the diagram**: Raw findings enter at the top (potentially hundreds). Dedup removes known duplicates and false positives. CVSS draft scoring estimates severity. Context enrichment adds CVE/CWE references and exploitability indicators. The model-judged triage — a secondary LLM call — evaluates each finding for actual exploitability in context and scope relevance. Only critical/high exploitable in-scope findings surface immediately; medium/low batch for the report; confirmed FPs and out-of-scope findings are logged but discarded. The pipeline turns 200 raw findings into 1-3 actionable reports.
