mirror of
https://github.com/github/awesome-copilot.git
synced 2026-04-14 04:05:58 +00:00
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:
@@ -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]
|
||||
````
|
||||
@@ -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`)
|
||||
@@ -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. -->
|
||||
@@ -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.*")
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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] |
|
||||
```
|
||||
@@ -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`)
|
||||
Reference in New Issue
Block a user