Teaching Script — Module S07: Threat Modeling Harnesses

Module: S07 — Threat Modeling Harnesses · Duration: ~60 minutes Format: Verbatim transcript. Cues [SLIDE N] map to 03-slide-deck.html.


[SLIDE 1 — Title]

This is Module S Zero Seven: Threat Modeling Harnesses. Sixty minutes. The second module of Pillar Two. Where the code review harness from S Zero Six shifts left, from reviewing code to reviewing architecture. Three sub-sections: architecture ingestion, the STRIDE analysis engine, and mitigation generation with issue tracking. By the end you can build a harness that ingests Terraform and OpenAPI, converts it to a data flow diagram, runs STRIDE per element, generates grounded threats, and files mitigations as issues engineers actually see.

[SLIDE 2 — Why threat modeling fails]

Let us start with why threat modeling fails in most organizations. It is manual. An architect draws a diagram in a quarterly meeting. A security engineer writes a spreadsheet of threats. The diagram goes stale the day someone merges a Terraform change, and nobody re-runs the model. The root cause is that the model is hand-maintained, separate from the architecture it describes.

The fix is to generate the model from the architecture as-written — infrastructure-as-code, OpenAPI specs — and regenerate on every change. The threat model becomes an output of the pipeline, not a hand-maintained artifact.

[SLIDE 3 — S07.1: Architecture Ingestion]

Sub-section one. Architecture ingestion. The harness ingests from the artifacts the engineering team already maintains. Terraform and CloudFormation — infrastructure as declared. OpenAPI and Swagger — API endpoints and schemas. Draw dot io and Mermaid diagrams — supplementary context. Source structure — service boundaries.

The strongest ingestion path is IaC plus OpenAPI, because those are machine-verifiable declarations of what is actually deployed. Draw dot io diagrams are useful but they are documentation, not source of truth — they drift. The harness treats IaC as authoritative and diagrams as supplementary.

Every input source normalizes to a canonical Data Flow Diagram representation — elements, flows, trust boundaries. The DFD is the intermediate representation. Every downstream stage operates on the DFD, not the raw input. This decouples ingestion from analysis. A new input source only needs a new parser that emits DFD elements and flows.

[SLIDE 4 — Trust boundary detection]

Trust boundary detection. A trust boundary is a line across which the level of trust changes — the edge between the public internet and your VPC, between a low-trust tenant and a high-trust admin service, between a third-party SaaS and your internal network. Trust boundaries are where the most dangerous threats live, because they are where an adversary can cross from a low-trust zone into a high-trust one.

The harness detects trust boundaries from the infrastructure declaration. Internet-facing resources — public IPs, internet gateways, public load balancer listeners — establish a boundary between the public internet and the VPC. IAM cross-account roles establish boundaries between accounts. Tenant isolation constructs — per-tenant schemas, tenant-scoped policies — establish boundaries between tenants. Each flow is marked crosses-boundary if its source and target are in different boundaries. The STRIDE engine treats these crossings as its highest-priority analysis targets.

[SLIDE 5 — S07.2: STRIDE Analysis Engine]

Sub-section two. The STRIDE analysis engine. STRIDE is a mnemonic for six categories of threats. Spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege. The strength is not the taxonomy itself — it is that each category maps to specific DFD element types, giving you a systematic method rather than an open-ended brainstorm.

[SLIDE 6 — STRIDE per element]

The applicability is scoped. External actors are analyzed for spoofing and repudiation only — you don't elevate privilege on something already outside the boundary. Processes and services get all six categories — they are the richest attack surface. Data stores get tampering, repudiation, information disclosure, and denial of service — not spoofing. You don't impersonate a database. Data flows get tampering, information disclosure, and denial of service. This scoping prevents the engine from generating threats that don't apply, keeping the threat list focused and credible.

[SLIDE 7 — Grounded threat generation]

For each element-and-category pair, the engine generates candidate threats. A pure-template generator produces generic statements — "an attacker could spoof the API gateway." Useless. The LLM-driven generator produces specific, contextual threats grounded in the element's technologies, the flows crossing its boundary, and the data involved.

Without grounding: "an attacker might spoof authentication." That applies to any service and prompts no action. With grounding — the element is an API gateway backed by Cognito and Lambda, with PII crossing the internet-to-VPC boundary — the model produces: "an attacker with stolen Cognito user pool credentials could call the Lambda directly, bypassing the API gateway's rate limiting and WAF rules, draft CVSS network, low complexity, low privileges, high confidentiality impact." Grounding is the load-bearing instruction.

[SLIDE 8 — Dedup + traceability]

A full DFD with twenty elements and an average of three categories each produces sixty element-category pairs, each yielding two to five threats — potentially two hundred candidate threats. Many are duplicates or near-duplicates. The engine deduplicates via semantic similarity — each threat is embedded, threats above a similarity threshold are merged. After dedup, the engine prioritizes by a draft CVSS score.

Every threat carries element-id and category. This traceability is not decorative. When a developer asks "why did you flag this," the harness points to the specific DFD element and flow. When the architecture changes and the element is removed, the threats against it are automatically retired. Traceability is what makes the model maintainable across versions.

[SLIDE 9 — S07.3: Mitigation + Issue Tracking]

Sub-section three. Mitigation generation and issue tracking. A threat list without mitigations is a complaint. The harness generates a per-threat mitigation, maps it to authoritative controls, tracks its status, and files it where the engineering team already works.

[SLIDE 10 — Three-layer mitigation mapping]

The mapping has three layers. OWASP ASVS controls — for example V2.1.7 for MFA requirements. CWE remediations — CWE-308 for single-factor authentication. And cloud provider best practices — AWS IAM condition keys requiring MFA for role assumption.

The difference between a platitude and a mitigation is the mapping. "Use strong authentication" is a platitude. "Enable AWS IAM condition keys requiring MFA for the sts AssumeRole call in the Lambda execution policy, per OWASP ASVS V2.1.7" is a mitigation an engineer can implement in a PR. The implementation is concrete — a config, an IaC update, a code change — not a slogan.

[SLIDE 11 — Issue tracker integration]

Threats do not live in a separate security tool. They live where the engineering team works — GitHub, Linear, Jira. The harness auto-creates issues with the attack narrative, the CVSS draft, the mitigation, the OWASP/CWE/cloud references, and traceability back to the threat model. The integration is bidirectional when possible — the issue links back to the model, and the model's status updates when the issue closes. The goal is zero manual transcription between the security analysis and the engineering backlog.

[SLIDE 12 — Model versioning + diff]

Model versioning. Architectures change. A threat model that is not versioned is a snapshot that goes stale. The harness diffs two model versions to identify what changed. New elements trigger STRIDE analysis. Removed elements retire their threats — traceability makes this automatic. New flows, especially flows that newly cross a trust boundary, are the highest-priority deltas. A new public-to-internal path is where new exposures live. Changed trust boundaries — a resource that moved from private to public, a new cross-account role — trigger re-analysis of affected elements. Unchanged elements are skipped.

The cost scales with the change, not the size of the architecture. This is what makes continuous threat modeling tractable on a large system. You do not re-run STRIDE on the entire fifty-element model on every Terraform change. You run on the delta.

[SLIDE 13 — What you take into S08]

S Zero Eight moves to SDLC gate harnesses. The threat modeling harness is operational — architecture ingestion, STRIDE engine, mitigation mapping, issue tracking. The control plane shift from review-time checks to creation-time guardrails. Multi-scanner orchestration — SAST, SCA, secrets, IaC in parallel. Trend analysis and risk scoring. Vulnerability triage at scale with CVE, EPSS, and CISA KEV. From modeling threats to gating the pipeline.


[End of script]

# Teaching Script — Module S07: Threat Modeling Harnesses

**Module**: S07 — Threat Modeling Harnesses · **Duration**: ~60 minutes
**Format**: Verbatim transcript. Cues `[SLIDE N]` map to `03-slide-deck.html`.

---

[SLIDE 1 — Title]

This is Module S Zero Seven: Threat Modeling Harnesses. Sixty minutes. The second module of Pillar Two. Where the code review harness from S Zero Six shifts left, from reviewing code to reviewing architecture. Three sub-sections: architecture ingestion, the STRIDE analysis engine, and mitigation generation with issue tracking. By the end you can build a harness that ingests Terraform and OpenAPI, converts it to a data flow diagram, runs STRIDE per element, generates grounded threats, and files mitigations as issues engineers actually see.

[SLIDE 2 — Why threat modeling fails]

Let us start with why threat modeling fails in most organizations. It is manual. An architect draws a diagram in a quarterly meeting. A security engineer writes a spreadsheet of threats. The diagram goes stale the day someone merges a Terraform change, and nobody re-runs the model. The root cause is that the model is hand-maintained, separate from the architecture it describes.

The fix is to generate the model from the architecture as-written — infrastructure-as-code, OpenAPI specs — and regenerate on every change. The threat model becomes an output of the pipeline, not a hand-maintained artifact.

[SLIDE 3 — S07.1: Architecture Ingestion]

Sub-section one. Architecture ingestion. The harness ingests from the artifacts the engineering team already maintains. Terraform and CloudFormation — infrastructure as declared. OpenAPI and Swagger — API endpoints and schemas. Draw dot io and Mermaid diagrams — supplementary context. Source structure — service boundaries.

The strongest ingestion path is IaC plus OpenAPI, because those are machine-verifiable declarations of what is actually deployed. Draw dot io diagrams are useful but they are documentation, not source of truth — they drift. The harness treats IaC as authoritative and diagrams as supplementary.

Every input source normalizes to a canonical Data Flow Diagram representation — elements, flows, trust boundaries. The DFD is the intermediate representation. Every downstream stage operates on the DFD, not the raw input. This decouples ingestion from analysis. A new input source only needs a new parser that emits DFD elements and flows.

[SLIDE 4 — Trust boundary detection]

Trust boundary detection. A trust boundary is a line across which the level of trust changes — the edge between the public internet and your VPC, between a low-trust tenant and a high-trust admin service, between a third-party SaaS and your internal network. Trust boundaries are where the most dangerous threats live, because they are where an adversary can cross from a low-trust zone into a high-trust one.

The harness detects trust boundaries from the infrastructure declaration. Internet-facing resources — public IPs, internet gateways, public load balancer listeners — establish a boundary between the public internet and the VPC. IAM cross-account roles establish boundaries between accounts. Tenant isolation constructs — per-tenant schemas, tenant-scoped policies — establish boundaries between tenants. Each flow is marked crosses-boundary if its source and target are in different boundaries. The STRIDE engine treats these crossings as its highest-priority analysis targets.

[SLIDE 5 — S07.2: STRIDE Analysis Engine]

Sub-section two. The STRIDE analysis engine. STRIDE is a mnemonic for six categories of threats. Spoofing, tampering, repudiation, information disclosure, denial of service, elevation of privilege. The strength is not the taxonomy itself — it is that each category maps to specific DFD element types, giving you a systematic method rather than an open-ended brainstorm.

[SLIDE 6 — STRIDE per element]

The applicability is scoped. External actors are analyzed for spoofing and repudiation only — you don't elevate privilege on something already outside the boundary. Processes and services get all six categories — they are the richest attack surface. Data stores get tampering, repudiation, information disclosure, and denial of service — not spoofing. You don't impersonate a database. Data flows get tampering, information disclosure, and denial of service. This scoping prevents the engine from generating threats that don't apply, keeping the threat list focused and credible.

[SLIDE 7 — Grounded threat generation]

For each element-and-category pair, the engine generates candidate threats. A pure-template generator produces generic statements — "an attacker could spoof the API gateway." Useless. The LLM-driven generator produces specific, contextual threats grounded in the element's technologies, the flows crossing its boundary, and the data involved.

Without grounding: "an attacker might spoof authentication." That applies to any service and prompts no action. With grounding — the element is an API gateway backed by Cognito and Lambda, with PII crossing the internet-to-VPC boundary — the model produces: "an attacker with stolen Cognito user pool credentials could call the Lambda directly, bypassing the API gateway's rate limiting and WAF rules, draft CVSS network, low complexity, low privileges, high confidentiality impact." Grounding is the load-bearing instruction.

[SLIDE 8 — Dedup + traceability]

A full DFD with twenty elements and an average of three categories each produces sixty element-category pairs, each yielding two to five threats — potentially two hundred candidate threats. Many are duplicates or near-duplicates. The engine deduplicates via semantic similarity — each threat is embedded, threats above a similarity threshold are merged. After dedup, the engine prioritizes by a draft CVSS score.

Every threat carries element-id and category. This traceability is not decorative. When a developer asks "why did you flag this," the harness points to the specific DFD element and flow. When the architecture changes and the element is removed, the threats against it are automatically retired. Traceability is what makes the model maintainable across versions.

[SLIDE 9 — S07.3: Mitigation + Issue Tracking]

Sub-section three. Mitigation generation and issue tracking. A threat list without mitigations is a complaint. The harness generates a per-threat mitigation, maps it to authoritative controls, tracks its status, and files it where the engineering team already works.

[SLIDE 10 — Three-layer mitigation mapping]

The mapping has three layers. OWASP ASVS controls — for example V2.1.7 for MFA requirements. CWE remediations — CWE-308 for single-factor authentication. And cloud provider best practices — AWS IAM condition keys requiring MFA for role assumption.

The difference between a platitude and a mitigation is the mapping. "Use strong authentication" is a platitude. "Enable AWS IAM condition keys requiring MFA for the sts AssumeRole call in the Lambda execution policy, per OWASP ASVS V2.1.7" is a mitigation an engineer can implement in a PR. The implementation is concrete — a config, an IaC update, a code change — not a slogan.

[SLIDE 11 — Issue tracker integration]

Threats do not live in a separate security tool. They live where the engineering team works — GitHub, Linear, Jira. The harness auto-creates issues with the attack narrative, the CVSS draft, the mitigation, the OWASP/CWE/cloud references, and traceability back to the threat model. The integration is bidirectional when possible — the issue links back to the model, and the model's status updates when the issue closes. The goal is zero manual transcription between the security analysis and the engineering backlog.

[SLIDE 12 — Model versioning + diff]

Model versioning. Architectures change. A threat model that is not versioned is a snapshot that goes stale. The harness diffs two model versions to identify what changed. New elements trigger STRIDE analysis. Removed elements retire their threats — traceability makes this automatic. New flows, especially flows that newly cross a trust boundary, are the highest-priority deltas. A new public-to-internal path is where new exposures live. Changed trust boundaries — a resource that moved from private to public, a new cross-account role — trigger re-analysis of affected elements. Unchanged elements are skipped.

The cost scales with the change, not the size of the architecture. This is what makes continuous threat modeling tractable on a large system. You do not re-run STRIDE on the entire fifty-element model on every Terraform change. You run on the delta.

[SLIDE 13 — What you take into S08]

S Zero Eight moves to SDLC gate harnesses. The threat modeling harness is operational — architecture ingestion, STRIDE engine, mitigation mapping, issue tracking. The control plane shift from review-time checks to creation-time guardrails. Multi-scanner orchestration — SAST, SCA, secrets, IaC in parallel. Trend analysis and risk scoring. Vulnerability triage at scale with CVE, EPSS, and CISA KEV. From modeling threats to gating the pipeline.

---

[End of script]