Add threat-model-analyst skill: STRIDE-A threat modeling for repositories (#1177)

* Add threat-model-analyst skill: STRIDE-A threat modeling for repositories

Add a comprehensive threat model analysis skill that performs security audits
using STRIDE-A (STRIDE + Abuse) threat modeling, Zero Trust principles, and
defense-in-depth analysis.

Supports two modes:
- Single analysis: full STRIDE-A threat model producing architecture overviews,
  DFD diagrams, prioritized findings, and executive assessments
- Incremental analysis: security posture diff between baseline report and current
  code, producing standalone reports with embedded comparison

Includes bundled reference assets:
- Orchestrator workflows (full and incremental)
- Analysis principles and verification checklists
- Output format specifications and skeleton templates
- DFD diagram conventions and TMT element taxonomy

* Address PR review comments from Copilot reviewer

- Fix SKILL.md description: use single-quoted scalar, rename mode (2) to
  'Incremental analysis' with accurate description
- Replace 'Compare Mode (Deprecated)' sections with 'Comparing Commits or
  Reports' redirect (no deprecated language for first release)
- Fix skeleton-findings.md: move Tier 1 table rows under header, add
  CONDITIONAL-EMPTY block after END-REPEAT (matching Tier 2/3 structure)
- Fix skeleton-threatmodel.md and skeleton-architecture.md: use 4-backtick
  outer fences to avoid nested fence conflicts with inner mermaid fences
- Fix skeleton-incremental-html.md: correct section count from 9 to 8
- Fix output-formats.md: change status 'open' to 'Open' in JSON example,
  move stride_category warning outside JSON fence as blockquote
- Fix incremental-orchestrator.md: replace stale compare-output-formats.md
  reference with inline color conventions
- Regenerate docs/README.skills.md with updated description

* Address second round of Copilot review comments

- Fix diagram-conventions.md: bidirectional flow notation now uses <-->
  matching orchestrator.md and DFD templates
- Fix tmt-element-taxonomy.md: normalize SE.DF.SSH/LDAP/LDAPS to use
  SE.DF.TMCore.* prefix consistent with all other data flow IDs
- Fix output-formats.md: correct TMT category example from SQLDatabase
  to SQL matching taxonomy, fix component type from 'datastore' to
  'data_store' matching canonical enum, remove DaprSidecar from
  inbound_from per no-standalone-sidecar rule
- Fix 5 skeleton files: clarify VERBATIM instruction to 'copy the
  template content below (excluding the outer code fence)' to prevent
  agents from wrapping output in markdown fences
- Genericize product-specific names in examples: replace edgerag with
  myapp, BitNetManager with TaskProcessor, AzureLocalMCP with MyApp.Core,
  AzureLocalInfra with OnPremInfra, MilvusVectorDB with VectorDB

* Address third round of Copilot review comments

- Fix diagram-conventions.md: second bidirectional two-arrow pattern in
  Quick Reference section now uses <-->
- Fix incremental-orchestrator.md: renumber HTML sections 5-9 to 4-8
  matching skeleton-incremental-html.md 8-section structure
- Fix output-formats.md: add incremental-comparison.html to File List
  as conditional output for incremental mode
- Fix skeleton-inventory.md: add tmt_type, sidecars, and boundary_kind
  fields to match output-formats.md JSON schema example
This commit is contained in:
Vijay Chegu
2026-03-29 20:58:56 +00:00
committed by GitHub
parent d0fdc3a566
commit afba5b86b8
18 changed files with 5370 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
# Skeleton: 0.1-architecture.md
> **⛔ Copy the template content below VERBATIM (excluding the outer code fence). Replace `[FILL]` placeholders. Do NOT add/rename/reorder sections.**
> **⛔ Key Components table columns are EXACTLY: `Component | Type | Description`. DO NOT rename to `Role`, `Change`, `Function`.**
> **⛔ Technology Stack table columns are EXACTLY: `Layer | Technologies` (2 columns). DO NOT add `Version` column or rename `Layer` to `Category`.**
> **⛔ Security Infrastructure Inventory and Repository Structure sections are MANDATORY — do NOT omit them.**
---
````markdown
# Architecture Overview
## System Purpose
[FILL-PROSE: 2-4 sentences — what is this system, what problem does it solve, who are the users]
## Key Components
| Component | Type | Description |
|-----------|------|-------------|
[REPEAT: one row per component]
| [FILL: PascalCase name] | [FILL: Process / Data Store / External Service / External Interactor] | [FILL: one-line description] |
[END-REPEAT]
<!-- ⛔ POST-TABLE CHECK: Verify Key Components:
1. Every component has PascalCase name (not kebab-case or snake_case)
2. Type is one of: Process / Data Store / External Service / External Interactor
3. Row count matches the number of nodes in the Component Diagram below
If ANY check fails → FIX NOW. -->
## Component Diagram
```mermaid
[FILL: Architecture diagram using service/external/datastore styles — NOT DFD circles]
```
## Top Scenarios
[REPEAT: 3-5 scenarios. First 3 MUST include sequence diagrams.]
### Scenario [FILL: N]: [FILL: Title]
[FILL-PROSE: 2-3 sentence description]
```mermaid
sequenceDiagram
[FILL: participants, messages, alt/opt blocks]
```
[END-REPEAT]
<!-- ⛔ POST-SECTION CHECK: Verify Top Scenarios:
1. At least 3 scenarios listed
2. First 3 scenarios MUST have sequenceDiagram blocks
3. Each sequence diagram has participant lines and message arrows
If ANY check fails → FIX NOW. -->
## Technology Stack
| Layer | Technologies |
|-------|--------------|
| Languages | [FILL] |
| Frameworks | [FILL] |
| Data Stores | [FILL] |
| Infrastructure | [FILL] |
| Security | [FILL] |
<!-- ⛔ POST-TABLE CHECK: Verify Technology Stack has all 5 rows filled. If Security row is empty, list security-relevant libraries/frameworks found in the code. -->
## Deployment Model
[FILL-PROSE: deployment description — ports, protocols, bind addresses, network exposure, topology (single machine / cluster / multi-tier)]
**Deployment Classification:** `[FILL: one of LOCALHOST_DESKTOP | LOCALHOST_SERVICE | AIRGAPPED | K8S_SERVICE | NETWORK_SERVICE]`
<!-- ⛔ DEPLOYMENT CLASSIFICATION RULES:
LOCALHOST_DESKTOP — Single-process console/GUI app, no network listeners (or localhost-only), single-user workstation. T1 FORBIDDEN.
LOCALHOST_SERVICE — Daemon/service binding to 127.0.0.1 only. T1 FORBIDDEN.
AIRGAPPED — No internet connectivity. T1 forbidden for network-originated attacks.
K8S_SERVICE — Kubernetes Deployment/StatefulSet with ClusterIP or LoadBalancer. T1 allowed.
NETWORK_SERVICE — Public API, cloud endpoint, internet-facing. T1 allowed.
This classification is BINDING on all subsequent prerequisite and tier assignments. -->
### Component Exposure Table
| Component | Listens On | Auth Required | Reachability | Min Prerequisite | Derived Tier |
|-----------|------------|---------------|--------------|------------------|-------------|
[REPEAT: one row per component from Key Components table]
| [FILL: component name] | [FILL: port/address or "N/A — no listener"] | [FILL: Yes (mechanism) / No] | [FILL: one of: External / Internal Only / Localhost Only / No Listener] | [FILL: one of closed enum — see rules below] | [FILL: T1 / T2 / T3] |
[END-REPEAT]
<!-- ⛔ EXPOSURE TABLE RULES:
1. Every component from Key Components MUST have a row.
2. "Listens On" = the actual bind address from code (e.g., "127.0.0.1:8080", "0.0.0.0:443", "N/A — no listener").
3. "Reachability" MUST be one of these 4 values (closed enum):
- `External` — reachable from public internet or untrusted network
- `Internal Only` — reachable only within a private network (K8s cluster, VNet, etc.)
- `Localhost Only` — binds to 127.0.0.1 or named pipe, same-host only
- `No Listener` — does not accept inbound connections (outbound-only, console I/O, library)
4. "Min Prerequisite" MUST be one of these values (closed enum):
- `None` — only valid when Reachability = External AND Auth Required = No
- `Authenticated User` — Reachability = External AND Auth Required = Yes
- `Internal Network` — Reachability = Internal Only AND Auth Required = No
- `Privileged User` — requires admin/operator role
- `Local Process Access` — Reachability = Localhost Only (same-host process can connect)
- `Host/OS Access` — Reachability = No Listener (requires filesystem, console, or debug access)
- `Admin Credentials` — requires admin credentials + host access
- `Physical Access` — requires physical presence
⛔ FORBIDDEN values: `Application Access`, `Host Access` (ambiguous — use `Local Process Access` or `Host/OS Access` instead)
5. "Derived Tier" is mechanically determined from Min Prerequisite:
- `None` → T1
- `Authenticated User`, `Privileged User`, `Internal Network`, `Local Process Access` → T2
- `Host/OS Access`, `Admin Credentials`, `Physical Access`, `{Component} Compromise`, or any `A + B` → T3
6. No threat or finding for this component may have a LOWER prerequisite than Min Prerequisite.
7. No threat or finding for this component may have a HIGHER tier (lower number) than Derived Tier.
8. This table is the SINGLE SOURCE OF TRUTH for prerequisite floors and tier ceilings. STRIDE and findings MUST respect it. -->
## Security Infrastructure Inventory
| Component | Security Role | Configuration | Notes |
|-----------|---------------|---------------|-------|
[REPEAT: one row per security-relevant component found in code]
| [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
## Repository Structure
| Directory | Purpose |
|-----------|---------|
[REPEAT: one row per key directory]
| [FILL: path/] | [FILL] |
[END-REPEAT]
````

View File

@@ -0,0 +1,273 @@
# Skeleton: 0-assessment.md
> **⛔ Copy the template content below VERBATIM (excluding the outer code fence). Replace `[FILL]` placeholders. Do NOT add/rename/reorder sections.**
> `[FILL]` = single value | `[FILL-PROSE]` = paragraphs | `[REPEAT]...[END-REPEAT]` = N copies | `[CONDITIONAL]...[END-CONDITIONAL]` = include if condition met
---
```markdown
# Security Assessment
---
## Report Files
| File | Description |
|------|-------------|
| [0-assessment.md](0-assessment.md) | This document — executive summary, risk rating, action plan, metadata |
| [0.1-architecture.md](0.1-architecture.md) | Architecture overview, components, scenarios, tech stack |
| [1-threatmodel.md](1-threatmodel.md) | Threat model DFD diagram with element, flow, and boundary tables |
| [1.1-threatmodel.mmd](1.1-threatmodel.mmd) | Pure Mermaid DFD source file |
| [2-stride-analysis.md](2-stride-analysis.md) | Full STRIDE-A analysis for all components |
| [3-findings.md](3-findings.md) | Prioritized security findings with remediation |
[CONDITIONAL: Include if 1.2-threatmodel-summary.mmd was generated]
| [1.2-threatmodel-summary.mmd](1.2-threatmodel-summary.mmd) | Summary DFD for large systems |
[END-CONDITIONAL]
[CONDITIONAL: Include for incremental analysis]
| [incremental-comparison.html](incremental-comparison.html) | Visual comparison report |
[END-CONDITIONAL]
<!-- ⛔ POST-TABLE CHECK: Verify Report Files:
1. `0-assessment.md` is the FIRST row (not 0.1-architecture.md)
2. All generated files are listed
3. Conditional rows (1.2-threatmodel-summary.mmd, incremental-comparison.html) only if those files exist
If ANY check fails → FIX NOW. -->
---
## Executive Summary
[FILL-PROSE: 2-3 paragraph summary of the system and its security posture]
[FILL: "The analysis covers [N] system elements across [M] trust boundaries."]
### Risk Rating: [FILL: Critical / Elevated / Moderate / Low]
[FILL-PROSE: risk rating justification paragraph]
> **Note on threat counts:** This analysis identified [FILL: N] threats across [FILL: M] components. This count reflects comprehensive STRIDE-A coverage, not systemic insecurity. Of these, **[FILL: T1 count] are directly exploitable** without prerequisites (Tier 1). The remaining [FILL: T2+T3 count] represent conditional risks and defense-in-depth considerations.
<!-- ⛔ POST-SECTION CHECK: Verify Executive Summary:
1. Risk Rating heading has NO emojis: `### Risk Rating: Elevated` not `### Risk Rating: 🟠 Elevated`
2. Note on threat counts blockquote is present
3. Element count and boundary count match actual counts from 1-threatmodel.md
If ANY check fails → FIX NOW. -->
---
## Action Summary
| Tier | Description | Threats | Findings | Priority |
|------|-------------|---------|----------|----------|
| [Tier 1](3-findings.md#tier-1--direct-exposure-no-prerequisites) | Directly exploitable | [FILL] | [FILL] | 🔴 Critical Risk |
| [Tier 2](3-findings.md#tier-2--conditional-risk-authenticated--single-prerequisite) | Requires authenticated access | [FILL] | [FILL] | 🟠 Elevated Risk |
| [Tier 3](3-findings.md#tier-3--defense-in-depth-prior-compromise--host-access) | Requires prior compromise | [FILL] | [FILL] | 🟡 Moderate Risk |
| **Total** | | **[FILL]** | **[FILL]** | |
<!-- ⛔ POST-TABLE CHECK: Verify Action Summary:
1. EXACTLY 4 data rows: Tier 1, Tier 2, Tier 3, Total — NO 'Mitigated', 'Platform', or 'Fixed' rows
2. Priority column is FIXED: Tier 1=🔴 Critical Risk, Tier 2=🟠 Elevated Risk, Tier 3=🟡 Moderate Risk — never changed based on counts
3. Threats column sums match 2-stride-analysis.md Totals row
4. Findings column sums match 3-findings.md FIND- heading count
5. Tier 1/2/3 cells are hyperlinks to 3-findings.md tier headings — verify anchors resolve
If ANY check fails → FIX NOW before continuing. -->
### Priority by Tier and CVSS Score (Top 10)
| Finding | Tier | CVSS Score | SDL Severity | Title |
|---------|------|------------|-------------|-------|
[REPEAT: top 10 findings only, sorted by Tier (T1 first, then T2, then T3), then by CVSS score descending within each tier]
| [FIND-XX](3-findings.md#find-xx-title-slug) | T[FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
<!-- ⛔ POST-TABLE CHECK: Verify Priority by Tier and CVSS Score:
1. Maximum 10 rows (top 10 findings only, not all findings)
2. Sort order: ALL Tier 1 findings first (by CVSS desc), then Tier 2 (by CVSS desc), then Tier 3 (by CVSS desc)
3. Every Finding cell is a hyperlink: [FIND-XX](3-findings.md#find-xx-title-slug)
4. Verify each hyperlink anchor resolves: compute the anchor from the ACTUAL heading text in 3-findings.md (lowercase, spaces→hyphens, strip special chars). The link must match whatever the heading is.
5. CVSS scores match the actual finding's CVSS value in 3-findings.md
If ANY check fails → FIX NOW. -->
### Quick Wins
<!-- Quick Wins Finding column: each Finding cell MUST be a hyperlink to 3-findings.md, same format as Priority table:
[FIND-XX](3-findings.md#find-xx-title-slug)
Compute the anchor from the ACTUAL heading text in 3-findings.md. -->
| Finding | Title | Why Quick |
|---------|-------|-----------|
[REPEAT]
| [FIND-XX](3-findings.md#find-xx-title-slug) | [FILL] | [FILL] |
[END-REPEAT]
---
[CONDITIONAL: Include ONLY for incremental analysis]
## Change Summary
### Component Changes
| Status | Count | Components |
|--------|-------|------------|
| Unchanged | [FILL] | [FILL] |
| Modified | [FILL] | [FILL] |
| New | [FILL] | [FILL] |
| Removed | [FILL] | [FILL] |
### Threat Status
| Status | Count |
|--------|-------|
| Existing | [FILL] |
| Fixed | [FILL] |
| New | [FILL] |
| Removed | [FILL] |
### Finding Status
| Status | Count |
|--------|-------|
| Existing | [FILL] |
| Fixed | [FILL] |
| Partial | [FILL] |
| New | [FILL] |
| Removed | [FILL] |
### Risk Direction
[FILL: Improving / Worsening / Stable] — [FILL-PROSE: 1-2 sentence justification]
---
## Previously Unidentified Issues
[FILL-PROSE: or "No previously unidentified issues found."]
| Finding | Title | Component | Evidence |
|---------|-------|-----------|----------|
[REPEAT]
| [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
[END-CONDITIONAL]
---
## Analysis Context & Assumptions
### Analysis Scope
| Constraint | Description |
|------------|-------------|
| Scope | [FILL] |
| Excluded | [FILL] |
| Focus Areas | [FILL] |
### Infrastructure Context
| Category | Discovered from Codebase | Findings Affected |
|----------|--------------------------|-------------------|
[REPEAT]
| [FILL] | [FILL: include relative file links] | [FILL] |
[END-REPEAT]
### Needs Verification
| Item | Question | What to Check | Why Uncertain |
|------|----------|---------------|---------------|
[REPEAT]
| [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
### Finding Overrides
| Finding ID | Original Severity | Override | Justification | New Status |
|------------|-------------------|----------|---------------|------------|
| — | — | — | No overrides applied. Update this section after review. | — |
### Additional Notes
[FILL-PROSE: or "No additional notes."]
---
## References Consulted
### Security Standards
| Standard | URL | How Used |
|----------|-----|----------|
| Microsoft SDL Bug Bar | https://www.microsoft.com/en-us/msrc/sdlbugbar | Severity classification |
| OWASP Top 10:2025 | https://owasp.org/Top10/2025/ | Threat categorization |
| CVSS 4.0 | https://www.first.org/cvss/v4.0/specification-document | Risk scoring |
| CWE | https://cwe.mitre.org/ | Weakness classification |
| STRIDE | https://learn.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats | Threat enumeration |
[REPEAT: additional standards if used]
| [FILL] | [FILL] | [FILL] |
[END-REPEAT]
### Component Documentation
| Component | Documentation URL | Relevant Section |
|-----------|------------------|------------------|
[REPEAT]
| [FILL] | [FILL] | [FILL] |
[END-REPEAT]
---
## Report Metadata
| Field | Value |
|-------|-------|
| Source Location | `[FILL]` |
| Git Repository | `[FILL]` |
| Git Branch | `[FILL]` |
| Git Commit | `[FILL: SHA from git rev-parse --short HEAD]` (`[FILL: date from git log -1 --format="%ai" — NOT today's date]`) |
| Model | `[FILL]` |
| Machine Name | `[FILL]` |
| Analysis Started | `[FILL]` |
| Analysis Completed | `[FILL]` |
| Duration | `[FILL]` |
| Output Folder | `[FILL]` |
| Prompt | `[FILL: the user's prompt text that triggered this analysis]` |
[CONDITIONAL: incremental]
| Baseline Report | `[FILL]` |
| Baseline Commit | `[FILL: SHA]` (`[FILL: commit date]`) |
| Target Commit | `[FILL: SHA]` (`[FILL: commit date]`) |
| Baseline Worktree | `[FILL]` |
| Analysis Mode | `Incremental` |
[END-CONDITIONAL]
<!-- ⛔ POST-TABLE CHECK: Verify Report Metadata:
1. ALL values wrapped in backticks: `value`
2. Git Commit, Baseline Commit, Target Commit each include date in parentheses
3. Duration field is present (not missing)
4. Model field states the actual model name
5. Analysis Started and Analysis Completed are real timestamps (not estimated from folder name)
If ANY check fails → FIX NOW. -->
---
## Classification Reference
<!-- SKELETON INSTRUCTION: Copy the table below verbatim. Do NOT modify values. Do NOT copy this HTML comment into the output. -->
| Classification | Values |
|---------------|--------|
| **Exploitability Tiers** | **T1** Direct Exposure (no prerequisites) · **T2** Conditional Risk (single prerequisite) · **T3** Defense-in-Depth (multiple prerequisites or infrastructure access) |
| **STRIDE + Abuse** | **S** Spoofing · **T** Tampering · **R** Repudiation · **I** Information Disclosure · **D** Denial of Service · **E** Elevation of Privilege · **A** Abuse (feature misuse) |
| **SDL Severity** | `Critical` · `Important` · `Moderate` · `Low` |
| **Remediation Effort** | `Low` · `Medium` · `High` |
| **Mitigation Type** | `Redesign` · `Standard Mitigation` · `Custom Mitigation` · `Existing Control` · `Accept Risk` · `Transfer Risk` |
| **Threat Status** | `Open` · `Mitigated` · `Platform` |
| **Incremental Tags** | `[Existing]` · `[Fixed]` · `[Partial]` · `[New]` · `[Removed]` (incremental reports only) |
| **CVSS** | CVSS 4.0 vector with `CVSS:4.0/` prefix |
| **CWE** | Hyperlinked CWE ID (e.g., [CWE-306](https://cwe.mitre.org/data/definitions/306.html)) |
| **OWASP** | OWASP Top 10:2025 mapping (e.g., A01:2025 Broken Access Control) |
```
**Critical format rules baked into this skeleton:**
- `0-assessment.md` is the FIRST row in Report Files (not `0.1-architecture.md`)
- `## Analysis Context & Assumptions` uses `&` (never word "and")
- `---` horizontal rules between EVERY pair of `## ` sections (minimum 6)
- `### Quick Wins` always present (with fallback note if no low-effort findings)
- `### Needs Verification` and `### Finding Overrides` always present (even if empty with `—`)
- References has TWO subsections with THREE-column tables (never flat 2-column)
- ALL metadata values wrapped in backticks
- ALL metadata fields present (Model, Analysis Started, Analysis Completed, Duration)
- Risk Rating heading has NO emojis
- Action Summary has EXACTLY 4 data rows: Tier 1, Tier 2, Tier 3, Total — NO "Mitigated" or "Platform" rows
- Git Commit rows include commit date in parentheses: `SHA` (`date`)

View File

@@ -0,0 +1,68 @@
# Skeleton: 1.1-threatmodel.mmd
> **⛔ This is a raw Mermaid file — NO markdown wrapper. Line 1 MUST start with `%%{init:`.**
> **The init block, classDefs, and linkStyle are FIXED — never change colors/strokes.**
> **Diagram direction is ALWAYS `flowchart LR` — NEVER `flowchart TB`.**
> **⛔ The template below is shown inside a code fence for readability only — do NOT include the fence in the output file.**
---
```
%%{init: {'theme': 'base', 'themeVariables': { 'background': '#ffffff', 'primaryColor': '#ffffff', 'lineColor': '#666666' }}}%%
flowchart LR
classDef process fill:#6baed6,stroke:#2171b5,stroke-width:2px,color:#000000
classDef external fill:#fdae61,stroke:#d94701,stroke-width:2px,color:#000000
classDef datastore fill:#74c476,stroke:#238b45,stroke-width:2px,color:#000000
[CONDITIONAL: incremental mode — include BOTH lines below]
classDef newComponent fill:#d4edda,stroke:#28a745,stroke-width:3px,color:#000000
classDef removedComponent fill:#e9ecef,stroke:#6c757d,stroke-width:1px,stroke-dasharray:5,color:#6c757d
[END-CONDITIONAL]
[REPEAT: one line per external actor/interactor — outside all subgraphs]
[FILL: NodeID]["[FILL: Display Name]"]:::external
[END-REPEAT]
[REPEAT: one subgraph per trust boundary]
subgraph [FILL: BoundaryID]["[FILL: Boundary Display Name]"]
[REPEAT: processes and datastores inside this boundary]
[FILL: NodeID](("[FILL: Process Name]")):::process
[FILL: NodeID][("[FILL: DataStore Name]")]:::datastore
[END-REPEAT]
end
[END-REPEAT]
[REPEAT: one line per data flow — use <--> for bidirectional request-response]
[FILL: SourceID] <-->|"[FILL: DF##: description]"| [FILL: TargetID]
[END-REPEAT]
[REPEAT: one style line per trust boundary subgraph]
style [FILL: BoundaryID] fill:none,stroke:#e31a1c,stroke-width:3px,stroke-dasharray: 5 5
[END-REPEAT]
linkStyle default stroke:#666666,stroke-width:2px
```
**NEVER change these fixed elements:**
- `%%{init:` themeVariables: only `background`, `primaryColor`, `lineColor`
- `flowchart LR` — never TB
- classDef colors: process=#6baed6/#2171b5, external=#fdae61/#d94701, datastore=#74c476/#238b45
- Incremental classDefs (when applicable): newComponent=#d4edda/#28a745 (light green), removedComponent=#e9ecef/#6c757d (gray dashed)
- New components MUST use `:::newComponent` (NOT `:::process`). Removed components MUST use `:::removedComponent`.
- Trust boundary style: `fill:none,stroke:#e31a1c,stroke-width:3px,stroke-dasharray: 5 5`
- linkStyle: `stroke:#666666,stroke-width:2px`
**DFD shapes:**
- Process: `(("Name"))` (double parentheses = circle)
- Data Store: `[("Name")]` (bracket-paren = cylinder)
- External: `["Name"]` (brackets = rectangle)
- All labels MUST be quoted in `""`
- All subgraph IDs: `subgraph ID["Title"]`
<!-- ⛔ POST-DFD GATE — IMMEDIATELY after creating this file:
1. Count element nodes: lines with (("...")), [("...")], ["..."] shapes
2. Count boundaries: lines with 'subgraph'
3. If elements > 15 OR boundaries > 4:
→ OPEN skeleton-summary-dfd.md and create 1.2-threatmodel-summary.mmd NOW
→ Do NOT proceed to 1-threatmodel.md until summary exists
4. If threshold NOT met → skip summary, proceed to 1-threatmodel.md
This is the most frequently skipped step. The gate is MANDATORY. -->

View File

@@ -0,0 +1,197 @@
# Skeleton: 3-findings.md
> **⛔ Copy the template content below VERBATIM (excluding the outer code fence). Replace `[FILL]` placeholders. ALL 10 attribute rows are MANDATORY per finding. Organize by TIER, not by severity.**
> **⛔ DO NOT abbreviate attribute names. Use EXACT names: `SDL Bugbar Severity` (not `Severity`), `Exploitation Prerequisites` (not `Prerequisites`), `Exploitability Tier` (not `Tier`), `Remediation Effort` (not `Effort`), `CVSS 4.0` (not `CVSS Score`).**
> **⛔ DO NOT use bold inline headers (`**Description:**`). Use `#### Description` markdown h4 headings.**
> **⛔ Tier section headings MUST be: `## Tier 1 — Direct Exposure (No Prerequisites)`, NOT `## Tier 1 Findings`.**
---
```markdown
# Security Findings
---
## Tier 1 — Direct Exposure (No Prerequisites)
[REPEAT: one finding block per Tier 1 finding, sorted by severity (Critical→Important→Moderate→Low) then CVSS descending]
### FIND-[FILL: NN]: [FILL: title]
| Attribute | Value |
|-----------|-------|
| SDL Bugbar Severity | [FILL: Critical / Important / Moderate / Low] |
| CVSS 4.0 | [FILL: N.N] (CVSS:4.0/[FILL: full vector starting with AV:]) |
| CWE | [CWE-[FILL: NNN]](https://cwe.mitre.org/data/definitions/[FILL: NNN].html): [FILL: weakness name] |
| OWASP | A[FILL: NN]:2025 [FILL: category name] |
| Exploitation Prerequisites | [FILL: text or "None"] |
| Exploitability Tier | Tier [FILL: 1/2/3] — [FILL: tier description] |
| Remediation Effort | [FILL: Low / Medium / High] |
| Mitigation Type | [FILL: Redesign / Standard Mitigation / Custom Mitigation / Existing Control / Accept Risk / Transfer Risk] |
| Component | [FILL: component name] |
| Related Threats | [T[FILL: NN].[FILL: X]](2-stride-analysis.md#[FILL: component-anchor]), [T[FILL: NN].[FILL: X]](2-stride-analysis.md#[FILL: component-anchor]) |
<!-- ⛔ POST-FINDING CHECK: Verify this finding IMMEDIATELY:
1. ALL 10 attribute rows present (SDL Bugbar Severity through Related Threats)
2. Row names are EXACT: 'SDL Bugbar Severity' (not 'SDL Bugbar'), 'Exploitation Prerequisites' (not 'Prerequisites'), 'Exploitability Tier' (not 'Risk Tier'), 'Remediation Effort' (not 'Effort')
3. Related Threats are HYPERLINKS with `](2-stride-analysis.md#` — NOT plain text like 'T01.S, T02.T'
4. CVSS starts with `CVSS:4.0/` — NOT bare vector
5. CWE is a hyperlink to cwe.mitre.org — NOT plain text
6. OWASP uses `:2025` suffix — NOT `:2021`
If ANY check fails → FIX THIS FINDING NOW before writing the next one. -->
#### Description
[FILL-PROSE: technical description of the vulnerability]
#### Evidence
**Prerequisite basis:** [FILL: cite the specific code/config that determines this finding's prerequisite — e.g., "binds to 127.0.0.1 only (src/Server.cs:42)", "no auth middleware on /api routes (Startup.cs:18)", "console app with no network listener (Program.cs)". This MUST match the Component Exposure Table in 0.1-architecture.md.]
[FILL: specific file paths, line numbers, config keys, code snippets]
#### Remediation
[FILL: actionable remediation steps]
#### Verification
[FILL: how to verify the fix was applied]
<!-- ⛔ POST-SECTION CHECK: Verify this finding's sub-sections:
1. Exactly 4 sub-headings present: `#### Description`, `#### Evidence`, `#### Remediation`, `#### Verification`
2. Sub-headings use `####` level (NOT bold `**Description:**` inline text)
3. No extra sub-headings like `#### Impact`, `#### Recommendation`, `#### Mitigation`
4. Description has at least 2 sentences of technical detail
5. Evidence cites specific file paths or line numbers (not generic)
If ANY check fails → FIX NOW before moving to next finding. -->
[END-REPEAT]
[CONDITIONAL-EMPTY: If no Tier 1 findings, include this line instead of the REPEAT block]
*No Tier 1 findings identified for this repository.*
[END-CONDITIONAL-EMPTY]
---
## Tier 2 — Conditional Risk (Authenticated / Single Prerequisite)
[REPEAT: same finding block structure as Tier 1, sorted same way]
### FIND-[FILL: NN]: [FILL: title]
| Attribute | Value |
|-----------|-------|
| SDL Bugbar Severity | [FILL] |
| CVSS 4.0 | [FILL] (CVSS:4.0/[FILL]) |
| CWE | [CWE-[FILL]](https://cwe.mitre.org/data/definitions/[FILL].html): [FILL] |
| OWASP | A[FILL]:2025 [FILL] |
| Exploitation Prerequisites | [FILL] |
| Exploitability Tier | Tier [FILL] — [FILL] |
| Remediation Effort | [FILL] |
| Mitigation Type | [FILL] |
| Component | [FILL] |
| Related Threats | [FILL] |
#### Description
[FILL-PROSE]
#### Evidence
**Prerequisite basis:** [FILL: cite the specific code/config that determines this finding's prerequisite — must match the Component Exposure Table in 0.1-architecture.md]
[FILL]
#### Remediation
[FILL]
#### Verification
[FILL]
[END-REPEAT]
[CONDITIONAL-EMPTY: If no Tier 2 findings, include this line instead of the REPEAT block]
*No Tier 2 findings identified for this repository.*
[END-CONDITIONAL-EMPTY]
---
## Tier 3 — Defense-in-Depth (Prior Compromise / Host Access)
[REPEAT: same finding block structure]
### FIND-[FILL: NN]: [FILL: title]
| Attribute | Value |
|-----------|-------|
| SDL Bugbar Severity | [FILL] |
| CVSS 4.0 | [FILL] (CVSS:4.0/[FILL]) |
| CWE | [CWE-[FILL]](https://cwe.mitre.org/data/definitions/[FILL].html): [FILL] |
| OWASP | A[FILL]:2025 [FILL] |
| Exploitation Prerequisites | [FILL] |
| Exploitability Tier | Tier [FILL] — [FILL] |
| Remediation Effort | [FILL] |
| Mitigation Type | [FILL] |
| Component | [FILL] |
| Related Threats | [FILL] |
#### Description
[FILL-PROSE]
#### Evidence
**Prerequisite basis:** [FILL: cite the specific code/config that determines this finding's prerequisite — must match the Component Exposure Table in 0.1-architecture.md]
[FILL]
#### Remediation
[FILL]
#### Verification
[FILL]
[END-REPEAT]
[CONDITIONAL-EMPTY: If no Tier 3 findings, include this line instead of the REPEAT block]
*No Tier 3 findings identified for this repository.*
[END-CONDITIONAL-EMPTY]
```
At the END of `3-findings.md`, append the Threat Coverage Verification table:
```markdown
---
## Threat Coverage Verification
| Threat ID | Finding ID | Status |
|-----------|------------|--------|
[REPEAT: one row per threat from ALL components in 2-stride-analysis.md]
| [FILL: T##.X] | [FILL: FIND-## or —] | [FILL: ✅ Covered (FIND-XX) / ✅ Mitigated (FIND-XX) / 🔄 Mitigated by Platform] |
[END-REPEAT]
<!-- ⛔ POST-TABLE CHECK: Verify Threat Coverage Verification:
1. Status column uses ONLY these 3 values with emoji prefixes:
- `✅ Covered (FIND-XX)` — vulnerability needs remediation
- `✅ Mitigated (FIND-XX)` — team built a control (documented in finding)
- `🔄 Mitigated by Platform` — external platform handles it
2. Do NOT use plain text like "Finding", "Mitigated", "Covered" without the emoji
3. Do NOT use "Needs Review", "Accepted Risk", or "N/A"
4. Column headers are EXACTLY: `Threat ID | Finding ID | Status` (NOT `Threat | Finding | Status`)
5. Every threat from 2-stride-analysis.md appears in this table (no missing threats)
If ANY check fails → FIX NOW. -->
```
**Fixed rules baked into this skeleton:**
- Finding ID: `FIND-` prefix (never `F-`, `F01`, `Finding`)
- Attribute names: `SDL Bugbar Severity`, `Exploitation Prerequisites`, `Exploitability Tier`, `Remediation Effort` (exact — not abbreviated)
- CVSS: starts with `CVSS:4.0/` (never bare vector)
- CWE: hyperlinked (never plain text)
- OWASP: `:2025` suffix (never `:2021`)
- Related Threats: individual hyperlinks (never plain text)
- Sub-sections: `#### Description`, `#### Evidence`, `#### Remediation`, `#### Verification`
- Organized by TIER — no `## Critical Findings` or `## Mitigated` sections
- Exactly 3 tier sections (all mandatory, even if empty with "*No Tier N findings identified.*")

View File

@@ -0,0 +1,150 @@
# Skeleton: incremental-comparison.html
> **⛔ Self-contained HTML — ALL CSS inline. No CDN links. Follow this exact 8-section structure.**
---
The HTML report has exactly 8 sections in this order. Each section MUST be present.
## Section 1: Header + Comparison Cards
```html
<div class="header">
<div class="report-badge">INCREMENTAL THREAT MODEL COMPARISON</div>
<h1>[FILL: repo name]</h1>
</div>
<div class="comparison-cards">
<div class="compare-card baseline">
<div class="card-label">BASELINE</div>
<div class="card-hash">[FILL: baseline SHA]</div>
<div class="card-date">[FILL: baseline commit date from git log]</div>
<div class="risk-badge [FILL: old-class]">[FILL: old rating]</div>
</div>
<div class="compare-arrow"></div>
<div class="compare-card target">
<div class="card-label">TARGET</div>
<div class="card-hash">[FILL: target SHA]</div>
<div class="card-date">[FILL: target commit date from git log]</div>
<div class="risk-badge [FILL: new-class]">[FILL: new rating]</div>
</div>
<div class="compare-card trend">
<div class="card-label">TREND</div>
<div class="trend-direction [FILL: color]">[FILL: Improving / Worsening / Stable]</div>
<div class="trend-duration">[FILL: N months]</div>
</div>
</div>
```
<!-- SKELETON INSTRUCTION: Section 2 (Risk Shift) is merged into Section 1 above. The old separate risk-shift div is removed. The comparison-cards div replaces both the old subtitle + risk-shift + time-between box. -->
## Section 2: Metrics Bar (5 boxes)
```html
<div class="metrics-bar">
[FILL: Components: old → new (±N)]
[FILL: Trust Boundaries: old → new (±N)]
[FILL: Threats: old → new (±N)]
[FILL: Findings: old → new (±N)]
[FILL: Code Changes: N commits, M PRs — use git rev-list --count and git log --oneline --merges --grep="Merged PR"]
</div>
```
**MUST include Trust Boundaries as one of the 5 metrics. 5th box is Code Changes (NOT Time Between).**
## Section 3: Status Summary Cards (colored)
```html
<div class="status-cards">
<!-- Green card --> Fixed: [FILL: count] [FILL: 1-sentence summary, NO IDs]
<!-- Red card --> New: [FILL: count] [FILL: 1-sentence summary, NO IDs]
<!-- Amber card --> Previously Unidentified: [FILL: count] [FILL: 1-sentence summary, NO IDs]
<!-- Gray card --> Still Present: [FILL: count] [FILL: 1-sentence summary, NO IDs]
</div>
```
<!-- SKELETON INSTRUCTION: Status cards show COUNT + a short human-readable sentence ONLY.
DO NOT include threat IDs (T06.S, T02.E), finding IDs (FIND-14), or component names.
Good: "1 credential handling vulnerability remediated"
Good: "4 new components with 21 new threats identified"
Good: "No new threats or findings introduced"
Bad: "T06.S: DefaultAzureCredential → ManagedIdentityCredential"
Bad: "ConfigurationOrchestrator — 5 threats (T16.*), LLMService — 6 threats (T17.*)"
The detailed item-by-item breakdown with IDs belongs in Section 5 (Threat/Finding Status Breakdown). -->
**Status info appears ONLY here — NOT also in the metrics bar.**
## Section 4: Component Status Grid
```html
<table class="component-grid">
<tr><th>Component</th><th>Type</th><th>Status</th><th>Source Files</th></tr>
[REPEAT: one row per component with color-coded status badge]
<tr><td>[FILL]</td><td>[FILL]</td><td><span class="badge-[FILL: status]">[FILL]</span></td><td>[FILL]</td></tr>
[END-REPEAT]
</table>
```
## Section 5: Threat/Finding Status Breakdown
```html
<div class="status-breakdown">
[FILL: Grouped by status — Fixed items, New items, etc.]
[REPEAT: Each item: ID | Title | Component | Status]
[END-REPEAT]
</div>
```
## Section 6: STRIDE Heatmap with Deltas
```html
<table class="stride-heatmap">
<thead>
<tr>
<th>Component</th>
<th>S</th><th>T</th><th>R</th><th>I</th><th>D</th><th>E</th><th>A</th>
<th>Total</th>
<th class="divider"></th>
<th>T1</th><th>T2</th><th>T3</th>
</tr>
</thead>
<tbody>
[REPEAT: one row per component]
<tr>
<td>[FILL: component]</td>
<td>[FILL: S value] [FILL: delta indicator ▲/▼]</td>
... [same for T, R, I, D, E, A, Total] ...
<td class="divider"></td>
<td>[FILL: T1]</td><td>[FILL: T2]</td><td>[FILL: T3]</td>
</tr>
[END-REPEAT]
</tbody>
</table>
```
**MUST have 13 columns: Component + S + T + R + I + D + E + A + Total + divider + T1 + T2 + T3**
## Section 7: Needs Verification
```html
<div class="needs-verification">
[REPEAT: items where analysis disagrees with old report]
[FILL: item description]
[END-REPEAT]
</div>
```
## Section 8: Footer
```html
<div class="footer">
Model: [FILL] | Duration: [FILL]
Baseline: [FILL: folder] at [FILL: SHA]
Generated: [FILL: timestamp]
</div>
```
---
**Fixed CSS variables (use in `<style>` block):**
```css
--red: #dc3545; /* new vulnerability */
--green: #28a745; /* fixed/improved */
--amber: #fd7e14; /* previously unidentified */
--gray: #6c757d; /* still present */
--accent: #2171b5; /* modified/info */
```
**Fixed rules:**
- ALL CSS in inline `<style>` block — no external stylesheets
- Include `@media print` styles
- Heatmap MUST have T1/T2/T3 columns after divider
- Metrics bar MUST include Trust Boundaries
- Status data in cards ONLY — not duplicated in metrics bar
- HTML threat/finding totals MUST match markdown STRIDE summary totals

View File

@@ -0,0 +1,139 @@
# Skeleton: threat-inventory.json
> **⛔ Use EXACT field names shown below. Common errors: `display_name` (wrong→`display`), `category` (wrong→`stride_category`), `name` (wrong→`title`).**
> **⛔ The template below is shown inside a code fence for readability only — do NOT include the fence in the output file. The `.json` file must start with `{` on line 1.**
---
```json
{
"schema_version": "[FILL: 1.0 for standalone, 1.1 for incremental]",
"report_folder": "[FILL: threat-model-YYYYMMDD-HHmmss]",
"commit": "[FILL: short SHA]",
"commit_date": "[FILL: commit date UTC]",
"branch": "[FILL]",
"repository": "[FILL: remote URL]",
"analysis_timestamp": "[FILL: UTC timestamp]",
"model": "[FILL]",
"components": [
[REPEAT: sorted by id]
{
"id": "[FILL: PascalCase]",
"display": "[FILL: display name — NOT display_name]",
"type": "[FILL: process / external_service / data_store / external_interactor]",
"tmt_type": "[FILL: SE.P.TMCore.* / SE.EI.TMCore.* / SE.DS.TMCore.* from tmt-element-taxonomy.md]",
"boundary": "[FILL: boundary ID]",
"boundary_kind": "[FILL: MachineBoundary / NetworkBoundary / ClusterBoundary / ProcessBoundary / PrivilegeBoundary / SandboxBoundary]",
"aliases": [],
"source_files": ["[FILL: relative paths]"],
"source_directories": ["[FILL: relative dirs]"],
"fingerprint": {
"component_type": "[FILL: process / external_service / data_store / external_interactor]",
"boundary_kind": "[FILL: MachineBoundary / NetworkBoundary / ClusterBoundary / ProcessBoundary / PrivilegeBoundary / SandboxBoundary]",
"source_files": ["[FILL: relative paths]"],
"source_directories": ["[FILL: relative dirs — MUST NOT be empty for process-type]"],
"class_names": ["[FILL]"],
"namespace": "[FILL]",
"config_keys": [],
"api_routes": [],
"dependencies": [],
"inbound_from": ["[FILL: component IDs that send data TO this component]"],
"outbound_to": ["[FILL: component IDs this component sends data TO]"],
"protocols": ["[FILL: gRPC / HTTPS / SQL / etc.]"]
},
"sidecars": ["[FILL: co-located sidecar names, or empty array]"]
}
[END-REPEAT]
],
"boundaries": [
[REPEAT: sorted by id]
{
"id": "[FILL: PascalCase boundary ID]",
"display": "[FILL]",
"kind": "[FILL: MachineBoundary / NetworkBoundary / ClusterBoundary / ProcessBoundary / PrivilegeBoundary / SandboxBoundary]",
"aliases": [],
"contains": ["[FILL: component IDs]"],
"contains_fingerprint": "[FILL: sorted pipe-delimited component IDs]"
}
[END-REPEAT]
],
"flows": [
[REPEAT: sorted by id]
{
"id": "[FILL: DF_Source_to_Target]",
"from": "[FILL: component ID]",
"to": "[FILL: component ID]",
"protocol": "[FILL]",
"description": "[FILL: 1 sentence max]"
}
[END-REPEAT]
],
"threats": [
[REPEAT: sorted by id then identity_key.component_id]
{
"id": "[FILL: T##.X]",
"title": "[FILL: short title — REQUIRED]",
"description": "[FILL: 1 sentence — REQUIRED]",
"stride_category": "[FILL: S/T/R/I/D/E/A — SINGLE LETTER, NOT full word]",
"tier": [FILL: 1/2/3],
"prerequisites": "[FILL]",
"status": "[FILL: Open/Mitigated/Platform]",
"mitigation": "[FILL: 1 sentence or empty]",
"identity_key": {
"component_id": "[FILL: PascalCase — MUST be inside identity_key, NOT top-level]",
"data_flow_id": "[FILL: DF_Source_to_Target]",
"stride_category": "[FILL: S/T/R/I/D/E/A]",
"attack_surface": "[FILL: brief description of the attack surface]"
}
}
[END-REPEAT]
],
"findings": [
[REPEAT: sorted by id then identity_key.component_id]
{
"id": "[FILL: FIND-##]",
"title": "[FILL]",
"severity": "[FILL: Critical/Important/Moderate/Low]",
"cvss_score": [FILL: N.N],
"cvss_vector": "[FILL: CVSS:4.0/AV:...]",
"cwe": "[FILL: CWE-###]",
"owasp": "[FILL: A##:2025]",
"tier": [FILL: 1/2/3],
"effort": "[FILL: Low/Medium/High]",
"related_threats": ["[FILL: T##.X]"],
"evidence_files": ["[FILL: relative paths]"],
"component": "[FILL: display name]",
"identity_key": {
"component_id": "[FILL: PascalCase]",
"vulnerability": "[FILL: CWE-###]",
"attack_surface": "[FILL: file:key or endpoint]"
}
}
[END-REPEAT]
],
"metrics": {
"total_components": [FILL],
"total_boundaries": [FILL],
"total_flows": [FILL],
"total_threats": [FILL],
"total_findings": [FILL],
"threats_by_tier": { "T1": [FILL], "T2": [FILL], "T3": [FILL] },
"findings_by_tier": { "T1": [FILL], "T2": [FILL], "T3": [FILL] },
"threats_by_stride": { "S": [FILL], "T": [FILL], "R": [FILL], "I": [FILL], "D": [FILL], "E": [FILL], "A": [FILL] },
"findings_by_severity": { "Critical": [FILL], "Important": [FILL], "Moderate": [FILL], "Low": [FILL] }
}
}
```
**MANDATORY field name compliance:**
- `"display"` — NOT `"display_name"`, `"name"`
- `"stride_category"` — NOT `"category"` — SINGLE LETTER (S/T/R/I/D/E/A)
- `"title"` AND `"description"` — both required on every threat
- `identity_key.component_id` — component link INSIDE identity_key, NOT top-level
- Sort all arrays deterministically before writing

View File

@@ -0,0 +1,106 @@
# Skeleton: 2-stride-analysis.md
> **⛔ Copy the template content below VERBATIM (excluding the outer code fence). Replace `[FILL]` placeholders. The "A" in STRIDE-A is ALWAYS "Abuse" — NEVER "Authorization".**
> **⛔ Exploitability Tiers table MUST have EXACTLY 4 columns: `Tier | Label | Prerequisites | Assignment Rule`. DO NOT merge into 3 columns. DO NOT rename `Assignment Rule` to `Description`.**
> **⛔ Summary table MUST include a `Link` column: `Component | Link | S | T | R | I | D | E | A | Total | T1 | T2 | T3 | Risk`**
> **⛔ N/A Categories MUST use a table (`| Category | Justification |`), NOT prose/bullet points.**
---
```markdown
# STRIDE + Abuse Cases — Threat Analysis
> This analysis uses the standard **STRIDE** methodology (Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege) extended with **Abuse Cases** (business logic abuse, workflow manipulation, feature misuse). The "A" column in tables below represents Abuse — a supplementary category covering threats where legitimate features are misused for unintended purposes. This is distinct from Elevation of Privilege (E), which covers authorization bypass.
## Exploitability Tiers
Threats are classified into three exploitability tiers based on the prerequisites an attacker needs:
| Tier | Label | Prerequisites | Assignment Rule |
|------|-------|---------------|----------------|
| **Tier 1** | Direct Exposure | `None` | Exploitable by unauthenticated external attacker with NO prior access. The prerequisite field MUST say `None`. |
| **Tier 2** | Conditional Risk | Single prerequisite: `Authenticated User`, `Privileged User`, `Internal Network`, or single `{Boundary} Access` | Requires exactly ONE form of access. The prerequisite field has ONE item. |
| **Tier 3** | Defense-in-Depth | `Host/OS Access`, `Admin Credentials`, `{Component} Compromise`, `Physical Access`, or MULTIPLE prerequisites joined with `+` | Requires significant prior breach, infrastructure access, or multiple combined prerequisites. |
<!-- ⛔ POST-TABLE CHECK: Verify this table has EXACTLY 4 columns (Tier|Label|Prerequisites|Assignment Rule). If you wrote 3 columns or named the 4th column 'Description' or 'Example' → FIX NOW before continuing. -->
## Summary
| Component | Link | S | T | R | I | D | E | A | Total | T1 | T2 | T3 | Risk |
|-----------|------|---|---|---|---|---|---|---|-------|----|----|----|------|
[REPEAT: one row per component — numeric STRIDE counts, 0 is valid with N/A justification]
| [FILL: ComponentName] | [Link](#[FILL: anchor]) | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL: sum] | [FILL] | [FILL] | [FILL] | [FILL: Low/Medium/High/Critical] |
[END-REPEAT]
| **Totals** | | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | **[FILL]** | |
<!-- ⛔ POST-TABLE CHECK: Verify this Summary table:
1. Has 14 columns: Component | Link | S | T | R | I | D | E | A | Total | T1 | T2 | T3 | Risk
2. The 2nd column is a SEPARATE 'Link' column with `[Link](#anchor)` values — do NOT embed links inside the Component column
3. S+T+R+I+D+E+A = Total for every row
4. T1+T2+T3 = Total for every row
5. No row has ALL 1s in every STRIDE column (if so, the analysis is too shallow)
6. The 'A' column header represents 'Abuse' not 'Authorization'
If ANY check fails → FIX NOW before writing component sections. -->
---
[REPEAT: one section per component — do NOT include sections for external actors (Operator, EndUser)]
## [FILL: ComponentName]
**Trust Boundary:** [FILL: boundary name]
**Role:** [FILL: brief description]
**Data Flows:** [FILL: DF##, DF##, ...]
**Pod Co-location:** [FILL: sidecars if K8s, or "N/A" if not K8s]
### STRIDE-A Analysis
#### Tier 1 — Direct Exposure (No Prerequisites)
| ID | Category | Threat | Prerequisites | Affected Flow | Mitigation | Status |
|----|----------|--------|---------------|---------------|------------|--------|
[REPEAT: threat rows or "*No Tier 1 threats identified.*"]
| [FILL: T##.X] | [FILL: Spoofing/Tampering/Repudiation/Information Disclosure/Denial of Service/Elevation of Privilege/Abuse] | [FILL] | [FILL] | [FILL: DF##] | [FILL] | [FILL: Open/Mitigated/Platform] |
[END-REPEAT]
#### Tier 2 — Conditional Risk
| ID | Category | Threat | Prerequisites | Affected Flow | Mitigation | Status |
|----|----------|--------|---------------|---------------|------------|--------|
[REPEAT: threat rows or "*No Tier 2 threats identified.*"]
| [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
#### Tier 3 — Defense-in-Depth
| ID | Category | Threat | Prerequisites | Affected Flow | Mitigation | Status |
|----|----------|--------|---------------|---------------|------------|--------|
[REPEAT: threat rows or "*No Tier 3 threats identified.*"]
| [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
#### Categories Not Applicable
| Category | Justification |
|----------|---------------|
[REPEAT: one row per N/A STRIDE category — use "Abuse" not "Authorization" for the A category]
| [FILL: Spoofing/Tampering/Repudiation/Information Disclosure/Denial of Service/Elevation of Privilege/Abuse] | [FILL: 1-sentence justification] |
[END-REPEAT]
<!-- ⛔ POST-COMPONENT CHECK: Verify this component:
1. Category column uses full names (not abbreviations like 'S', 'T', 'DoS')
2. 'A' category is 'Abuse' (NEVER 'Authorization')
3. Status column uses ONLY: Open, Mitigated, Platform
4. All 3 tier sub-sections present (even if empty with '*No Tier N threats*')
5. N/A table present for any STRIDE categories without threats
If ANY check fails → FIX NOW before moving to next component. -->
[END-REPEAT]
```
**STRIDE + Abuse Cases — the 7 categories are EXACTLY:**
Spoofing | Tampering | Repudiation | Information Disclosure | Denial of Service | Elevation of Privilege | Abuse
**Note:** The first 6 are standard STRIDE. "Abuse" is a supplementary category for business logic misuse (workflow manipulation, feature exploitation, API abuse). It is NOT "Authorization" — authorization issues belong under Elevation of Privilege (E).
**Valid Status values:** `Open` | `Mitigated` | `Platform` — NO other values permitted.

View File

@@ -0,0 +1,62 @@
# Skeleton: 1.2-threatmodel-summary.mmd
> **⛔ ALWAYS evaluate this skeleton after creating `1.1-threatmodel.mmd`.**
> Count elements (nodes with `(("..."))`, `[("...")]`, `["..."]`) and boundaries (`subgraph`) in the detailed DFD.
> - If elements > 15 OR boundaries > 4 → this file is **REQUIRED**. Fill the template below.
> - If elements ≤ 15 AND boundaries ≤ 4 → **SKIP** this file. Proceed to `1-threatmodel.md`.
> **⛔ This is a raw Mermaid file. The template below is shown inside a code fence for readability only — do NOT include the fence in the output file. The `.mmd` file must start with `%%{init:` on line 1.**
---
```
%%{init: {'theme': 'base', 'themeVariables': { 'background': '#ffffff', 'primaryColor': '#ffffff', 'lineColor': '#666666' }}}%%
flowchart LR
classDef process fill:#6baed6,stroke:#2171b5,stroke-width:2px,color:#000000
classDef external fill:#fdae61,stroke:#d94701,stroke-width:2px,color:#000000
classDef datastore fill:#74c476,stroke:#238b45,stroke-width:2px,color:#000000
[FILL: External actors — keep all, do not aggregate]
[FILL: ExternalActor]["[FILL: Name]"]:::external
[REPEAT: one subgraph per trust boundary — ALL boundaries MUST be preserved]
subgraph [FILL: BoundaryID]["[FILL: Boundary Name]"]
[FILL: Aggregated and individual nodes]
end
[END-REPEAT]
[REPEAT: summary data flows using SDF prefix]
[FILL: Source] <-->|"[FILL: SDF##: description]"| [FILL: Target]
[END-REPEAT]
[REPEAT: boundary styles]
style [FILL: BoundaryID] fill:none,stroke:#e31a1c,stroke-width:3px,stroke-dasharray: 5 5
[END-REPEAT]
linkStyle default stroke:#666666,stroke-width:2px
```
## Aggregation Rules
**Reference:** `diagram-conventions.md` → Summary Diagram Rules for full details.
1. **ALL trust boundaries MUST be preserved** — never combine or omit boundaries.
2. **Keep individually:** entry points, core flow components, security-critical services, primary data stores, all external actors.
3. **Aggregate only:** supporting infrastructure, secondary caches, multiple externals at same trust level.
4. **Aggregated element labels MUST list contents:**
```
DataLayer[("Data Layer<br/>(UserDB, OrderDB, Redis)")]
SupportServices(("Supporting<br/>(Logging, Monitoring)"))
```
5. **Flow IDs:** Use `SDF` prefix: `SDF01`, `SDF02`, ...
## Required in `1-threatmodel.md`
When this file is generated, `1-threatmodel.md` MUST include:
- A `## Summary View` section with this diagram in a ` ```mermaid ` fence
- A `## Summary to Detailed Mapping` table:
```markdown
| Summary Element | Contains | Summary Flows | Maps to Detailed Flows |
|----------------|----------|---------------|------------------------|
| [FILL] | [FILL: list of detailed elements] | [FILL: SDF##] | [FILL: DF## list] |
```

View File

@@ -0,0 +1,65 @@
# Skeleton: 1-threatmodel.md
> **⛔ Copy the template content below VERBATIM (excluding the outer code fence). Replace `[FILL]` placeholders. Diagram in `.md` and `.mmd` must be IDENTICAL.**
> **⛔ Data Flow Table columns: `ID | Source | Target | Protocol | Description`. DO NOT rename `Target` to `Destination`. DO NOT reorder columns.**
> **⛔ Trust Boundary Table columns: `Boundary | Description | Contains` (3 columns). DO NOT add a `Name` column or rename `Contains` to `Components Inside`.**
---
````markdown
# Threat Model
## Data Flow Diagram
```mermaid
[FILL: Copy EXACT content from 1.1-threatmodel.mmd]
```
## Element Table
| Element | Type | TMT Category | Description | Trust Boundary |
|---------|------|--------------|-------------|----------------|
[CONDITIONAL: For K8s apps with sidecars, add a `Co-located Sidecars` column after Trust Boundary]
[REPEAT: one row per element]
| [FILL] | [FILL: Process / External Interactor / Data Store] | [FILL: SE.P.TMCore.* / SE.EI.TMCore.* / SE.DS.TMCore.*] | [FILL] | [FILL] |
[END-REPEAT]
## Data Flow Table
| ID | Source | Target | Protocol | Description |
|----|--------|--------|----------|-------------|
[REPEAT: one row per data flow]
| [FILL: DF##] | [FILL] | [FILL] | [FILL] | [FILL] |
[END-REPEAT]
## Trust Boundary Table
| Boundary | Description | Contains |
|----------|-------------|----------|
[REPEAT: one row per trust boundary]
| [FILL] | [FILL] | [FILL: comma-separated component list] |
[END-REPEAT]
[CONDITIONAL: Include ONLY if summary diagram was generated (elements > 15 OR boundaries > 4)]
## Summary View
```mermaid
[FILL: Copy EXACT content from 1.2-threatmodel-summary.mmd]
```
## Summary to Detailed Mapping
| Summary Element | Contains | Summary Flows | Maps to Detailed Flows |
|-----------------|----------|---------------|------------------------|
[REPEAT]
| [FILL] | [FILL] | [FILL: SDF##] | [FILL: DF##, DF##] |
[END-REPEAT]
[END-CONDITIONAL]
````
**Fixed rules:**
- Use `DF01`, `DF02` for detailed flows; `SDF01`, `SDF02` for summary flows
- Element Type: exactly `Process`, `External Interactor`, or `Data Store`
- TMT Category: must be a specific ID from tmt-element-taxonomy.md (e.g., `SE.P.TMCore.WebSvc`)