Add tm7-threat-model skill for valid TM7 file generation (#2280)

* Add tm7-threat-model skill for valid TM7 file generation

Adds a skill that generates valid Microsoft Threat Modeling Tool (.tm7)
files using the correct WCF DataContractSerializer format, with a minimal
reference file. Includes STRIDE threat generation workflow and a checklist
of common serialization mistakes that corrupt .tm7 files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review: sanitize reference model, fix dangling refs, move to assets

- Move example-minimal.tm7 into assets/ per repo convention (aaronpowell).
- Remove personal/corporate metadata from the reference model (Owner,
  Contributors, ChangedBy domain account, project names).
- Make the reference model self-contained: add a second stencil so the data
  flow and threat SourceGuid/TargetGuid/FlowGuid all resolve to real elements.
- Fix SKILL.md threat contract (KeyValueOfstringThreatpc_P0_PhOB with
  b:-prefixed KnowledgeBase fields) to match the bundled reference.
- Reconcile guidance: MetaInformation/Notes/KnowledgeBase are valid schema
  elements and must be preserved; only SecurityGaps/Mitigations are invalid.
- Regenerate docs/README.skills.md and normalize line endings to LF.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address 2nd review: correct KnowledgeBase placement, valid TypeIds, z:Id uniqueness

- Document KnowledgeBase as a top-level sibling after ThreatMetaData (not embedded)
- Update skeleton to show <ThreatMetaData/>, sibling <KnowledgeBase>, and <Profile>
- Replace TypeIds absent from the bundled KB: AzureCosmosDB -> AzureSQLDB,
  HumanUser -> Mobile, GenericDataFlow -> Request
- Require z:Id uniqueness across the file in the common-mistakes checklist

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: exclude *.tm7 exports from codespell

MTM DataContract .tm7 exports embed base64 icon blobs whose substrings
(oT, bu, wth, mKe, ...) trigger codespell false positives. Skip *.tm7,
matching the existing convention for binary/asset files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: prasad <prasaddharaskar@gmail.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
This commit is contained in:
prasadgd9022
2026-07-15 04:42:29 +05:30
committed by GitHub
parent e353a8cfb8
commit 36b30eb113
4 changed files with 319 additions and 1 deletions
+2 -1
View File
@@ -63,5 +63,6 @@
ignore-words-list = numer,wit,aks,edn,ser,ois,gir,rouge,categor,aline,ative,afterall,deques,dateA,dateB,TE,FillIn,alle,vai,LOD,InOut,pixelX,aNULL,Wee,Sherif,queston,Vertexes,nin,FO,CAF,Parth,ans,gud,Vally,vally
# Skip certain files and directories
# *.tm7 - MTM DataContract exports; embedded base64 icon blobs trigger false positives
skip = .git,node_modules,package-lock.json,*.lock,website/build,website/.docusaurus,.all-contributorrc,./skills/geofeed-tuner/assets/*.json,./skills/geofeed-tuner/references/*.txt,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/assets/*.json,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/references/*.txt,./extensions/arcade-canvas/game/phaser.min.js
skip = .git,node_modules,package-lock.json,*.lock,website/build,website/.docusaurus,.all-contributorrc,./skills/geofeed-tuner/assets/*.json,./skills/geofeed-tuner/references/*.txt,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/assets/*.json,./plugins/fastah-ip-geo-tools/skills/geofeed-tuner/references/*.txt,./extensions/arcade-canvas/game/phaser.min.js,*.tm7
+1
View File
@@ -376,6 +376,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [threat-model-analyst](../skills/threat-model-analyst/SKILL.md)<br />`gh skills install github/awesome-copilot threat-model-analyst` | Full STRIDE-A threat model analysis and incremental update skill for repositories and systems. Supports two modes: (1) Single analysis — full STRIDE-A threat model of a repository, producing architecture overviews, DFD diagrams, STRIDE-A analysis, prioritized findings, and executive assessments. (2) Incremental analysis — takes a previous threat model report as baseline, compares the codebase at the latest (or a given commit), and produces an updated report with change tracking (new, resolved, still-present threats), STRIDE heatmap, findings diff, and an embedded HTML comparison. Only activate when the user explicitly requests a threat model analysis, incremental update, or invokes /threat-model-analyst directly. | `references/analysis-principles.md`<br />`references/diagram-conventions.md`<br />`references/incremental-orchestrator.md`<br />`references/orchestrator.md`<br />`references/output-formats.md`<br />`references/skeletons`<br />`references/tmt-element-taxonomy.md`<br />`references/verification-checklist.md` |
| [tiny-stepping](../skills/tiny-stepping/SKILL.md)<br />`gh skills install github/awesome-copilot tiny-stepping` | Incremental development workflow that makes the smallest meaningful change per step and pauses for feedback, so the direction gets validated early before continuing. Use for careful, iterative implementation with continuous validation. | None |
| [tldr-prompt](../skills/tldr-prompt/SKILL.md)<br />`gh skills install github/awesome-copilot tldr-prompt` | Create tldr summaries for GitHub Copilot files (prompts, agents, instructions, collections), MCP servers, or documentation from URLs and queries. | None |
| [tm7-threat-model](../skills/tm7-threat-model/SKILL.md)<br />`gh skills install github/awesome-copilot tm7-threat-model` | Creates valid Microsoft Threat Modeling Tool (.tm7) files compatible with the Microsoft Threat Modeling Tool v7.3+. Use this skill whenever asked to create, generate, or modify a .tm7 threat model file, or when performing STRIDE threat modeling that should output a .tm7 file that opens cleanly in the Microsoft Threat Modeling Tool. | `assets/example-minimal.tm7` |
| [transloadit-media-processing](../skills/transloadit-media-processing/SKILL.md)<br />`gh skills install github/awesome-copilot transloadit-media-processing` | Process media files (video, audio, images, documents) using Transloadit. Use when asked to encode video to HLS/MP4, generate thumbnails, resize or watermark images, extract audio, concatenate clips, add subtitles, OCR documents, or run any media processing pipeline. Covers 86+ processing robots for file transformation at scale. | None |
| [typescript-mcp-server-generator](../skills/typescript-mcp-server-generator/SKILL.md)<br />`gh skills install github/awesome-copilot typescript-mcp-server-generator` | Generate a complete MCP server project in TypeScript with tools, resources, and proper configuration | None |
| [typespec-api-operations](../skills/typespec-api-operations/SKILL.md)<br />`gh skills install github/awesome-copilot typespec-api-operations` | Add GET, POST, PATCH, and DELETE operations to a TypeSpec API plugin with proper routing, parameters, and adaptive cards | None |
+312
View File
@@ -0,0 +1,312 @@
---
name: tm7-threat-model
description: 'Creates valid Microsoft Threat Modeling Tool (.tm7) files compatible with the Microsoft Threat Modeling Tool v7.3+. Use this skill whenever asked to create, generate, or modify a .tm7 threat model file, or when performing STRIDE threat modeling that should output a .tm7 file that opens cleanly in the Microsoft Threat Modeling Tool.'
---
# Microsoft Threat Modeling Tool (.tm7) Generator
You generate **valid `.tm7` files** for the Microsoft Threat Modeling Tool (v7.3+). A `.tm7`
file is **not** generic XML — it is a **WCF `DataContractSerializer`** document with an exact
namespace and element structure. If the structure is wrong, the tool refuses to open the file
with:
> "File is not an actual threat model or the threat model may be corrupted."
Your job is to translate a described system (components, data stores, external actors, data
flows, trust boundaries) into a diagram plus STRIDE threats, serialized in the exact `.tm7`
format described below.
## Workflow
When asked to produce a `.tm7` file:
1. **Model the system.** Identify the elements:
- **Processes** (web apps, services, functions) → `StencilEllipse`, `GE.P`
- **Data stores** (databases, caches, queues, blobs) → `StencilParallelLines`, `GE.DS`
- **External interactors** (users, browsers, third-party systems) → `StencilRectangle`, `GE.EI`
- **Trust boundaries**`BorderBoundary`, `GE.TB`
- **Data flows** connecting the above → `Connector`, `GE.DF`
2. **Assign a unique lowercase UUID** (e.g. `148ade68-5c80-40f3-8e1f-4e2cabdb5991`) to every
stencil and every flow. Never use human-readable ids like `users-browser`.
3. **Lay out coordinates** (`Left`/`Top`/`Width`/`Height`) so stencils don't overlap.
4. **Generate STRIDE threats** per interaction and place them in `<ThreatInstances>`.
5. **Serialize** using the structure in this guide, mirroring `assets/example-minimal.tm7`.
6. **Validate** against the "Common Mistakes" checklist before returning the file.
7. **Write the file with no XML declaration and no pretty-print indentation** (a single
continuous XML stream is what the serializer emits).
Always open [`assets/example-minimal.tm7`](./assets/example-minimal.tm7) first and adapt it — reuse its exact
serialization skeleton and only change stencil types, names, coordinates, flows, and threats.
## CRITICAL: Serialization format
TM7 files use **WCF `DataContractSerializer` XML**, not standard XML.
The file MUST start with this exact root element — **no `<?xml?>` declaration**:
```xml
<ThreatModel xmlns="http://schemas.datacontract.org/2004/07/ThreatModeling.Model" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
```
**NEVER use:**
- `<?xml version="1.0" encoding="utf-8"?>` — causes deserialization failure.
- `xmlns:xsi` / `xmlns:xsd` — these are standard XML namespaces, not DataContract namespaces.
- Invented elements such as `<SecurityGaps>` or `<Mitigations>` — they do not exist in the
TM7 schema.
> **Note:** `<MetaInformation>` (with children like `<Owner>`, `<Contributors>`,
> `<Reviewer>`, `<Assumptions>`, `<ExternalDependencies>`, `<HighLevelSystemDescription>`,
> `<ThreatModelName>`), `<Notes>`, and `<KnowledgeBase>` **are** part of the real schema and
> are emitted by the tool — keep them (see the structure below and `assets/example-minimal.tm7`).
> Just don't invent elements that the tool never produces.
## Required namespace prefixes
| Prefix | URI | Used for |
|--------|-----|----------|
| (default) | `http://schemas.datacontract.org/2004/07/ThreatModeling.Model` | Root `ThreatModel` |
| `xmlns:i` | `http://www.w3.org/2001/XMLSchema-instance` | Type attributes |
| `xmlns:z` | `http://schemas.microsoft.com/2003/10/Serialization/` | Reference ids (`z:Id`) |
| `xmlns:a` | `http://schemas.microsoft.com/2003/10/Serialization/Arrays` | Arrays / collections |
| `xmlns:b` | `http://schemas.datacontract.org/2004/07/ThreatModeling.KnowledgeBase` | Stencil properties |
| `xmlns:c` | `http://www.w3.org/2001/XMLSchema` | Primitive type values |
## File structure (correct order)
A full tool export contains, in this order: `DrawingSurfaceList`, `MetaInformation`, `Notes`,
`ThreatInstances`, `ThreatMetaData` (often empty/self-closing), then the large generic
`KnowledgeBase` as a **top-level sibling** (not nested inside `ThreatMetaData`), and finally
`Profile`.
```xml
<ThreatModel xmlns="..." xmlns:i="...">
<DrawingSurfaceList>
<DrawingSurfaceModel z:Id="i1" xmlns:z="...">
<GenericTypeId xmlns="...Abstracts">DRAWINGSURFACE</GenericTypeId>
<Guid xmlns="...Abstracts">{guid}</Guid>
<Properties xmlns="...Abstracts" xmlns:a="...Arrays">...</Properties>
<TypeId xmlns="...Abstracts">DRAWINGSURFACE</TypeId>
<Borders xmlns:a="...Arrays">
<!-- Stencil elements: processes, data stores, external entities, boundaries -->
</Borders>
<Lines xmlns:a="...Arrays">
<!-- Data flow lines connecting stencils -->
</Lines>
<Notes xmlns:a="...Arrays"/>
</DrawingSurfaceModel>
</DrawingSurfaceList>
<MetaInformation>
<!-- Owner, Contributors, Reviewer, Assumptions, ThreatModelName, etc. -->
</MetaInformation>
<Notes xmlns:a="...Arrays"/>
<ThreatInstances>
<!-- Threat entries -->
</ThreatInstances>
<ThreatMetaData/>
<KnowledgeBase z:Id="i21" xmlns:a="...ThreatModeling.KnowledgeBase" xmlns:z="...">
<!-- Generic SDL stencil/threat catalog — top-level sibling of ThreatMetaData -->
</KnowledgeBase>
<Profile>
<PromptedKb xmlns=""/>
</Profile>
</ThreatModel>
```
> The `<KnowledgeBase>` (the generic SDL stencil/threat catalog) is large but **required**
> the tool uses it to resolve every stencil `TypeId`. It is a **top-level sibling** placed after
> `ThreatMetaData` and before `Profile`, **not** nested inside `ThreatMetaData`. Reuse it verbatim
> from `assets/example-minimal.tm7`; only add stencils whose `TypeId` already appears in that
> KnowledgeBase.
## Stencil elements
Each stencil in `<Borders>` is wrapped in `<a:KeyValueOfguidanyType>`:
```xml
<a:KeyValueOfguidanyType>
<a:Key>{guid}</a:Key>
<a:Value z:Id="i2" i:type="StencilEllipse">
<GenericTypeId xmlns="...Abstracts">GE.P</GenericTypeId>
<Guid xmlns="...Abstracts">{guid}</Guid>
<Properties xmlns="...Abstracts">
<a:anyType i:type="b:HeaderDisplayAttribute" xmlns:b="...KnowledgeBase">
<b:DisplayName>Web Application</b:DisplayName>
<b:Name/>
<b:Value i:nil="true"/>
</a:anyType>
<a:anyType i:type="b:StringDisplayAttribute" xmlns:b="...KnowledgeBase">
<b:DisplayName>Name</b:DisplayName>
<b:Name/>
<b:Value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">My Component</b:Value>
</a:anyType>
<!-- Out Of Scope, Reason, configurable attributes -->
</Properties>
<TypeId xmlns="...Abstracts">SE.P.TMCore.WebApp</TypeId>
<Height xmlns="...Abstracts">100</Height>
<Left xmlns="...Abstracts">400</Left>
<StrokeDashArray i:nil="true" xmlns="...Abstracts"/>
<StrokeThickness xmlns="...Abstracts">1</StrokeThickness>
<Top xmlns="...Abstracts">200</Top>
<Width xmlns="...Abstracts">100</Width>
</a:Value>
</a:KeyValueOfguidanyType>
```
### Stencil shape types
| Shape | `i:type` | `GenericTypeId` | Description |
|-------|----------|-----------------|-------------|
| Process (circle) | `StencilEllipse` | `GE.P` | Processes, web apps, services |
| Data store (parallel lines) | `StencilParallelLines` | `GE.DS` | Databases, storage, caches |
| External interactor (rectangle) | `StencilRectangle` | `GE.EI` | Users, external systems |
| Trust boundary | `BorderBoundary` | `GE.TB` | Trust boundaries |
### Common `TypeId` values (SDL TM knowledge base)
| `TypeId` | Component |
|----------|-----------|
| `SE.P.TMCore.WebApp` | Web Application |
| `SE.P.TMCore.AzureAppServiceWebApp` | Azure App Service Web App |
| `SE.P.TMCore.AzureEventHub` | Azure Event Hub |
| `SE.P.TMCore.DynamicsCRM` | Dynamics CRM |
| `SE.DS.TMCore.SQL` | SQL Database |
| `SE.DS.TMCore.AzureSQLDB` | Azure SQL Database |
| `SE.EI.TMCore.Browser` | Browser |
| `SE.EI.TMCore.Mobile` | Mobile Client |
## Data flow lines
Lines in `<Lines>` also use `<a:KeyValueOfguidanyType>`, with `i:type="Connector"`:
```xml
<a:KeyValueOfguidanyType>
<a:Key>{line-guid}</a:Key>
<a:Value z:Id="i10" i:type="Connector">
<GenericTypeId xmlns="...Abstracts">GE.DF</GenericTypeId>
<Guid xmlns="...Abstracts">{line-guid}</Guid>
<Properties xmlns="...Abstracts">...</Properties>
<TypeId xmlns="...Abstracts">SE.DF.TMCore.Request</TypeId>
<HandleX xmlns="...Abstracts">0</HandleX>
<HandleY xmlns="...Abstracts">0</HandleY>
<SourceGuid xmlns="...Abstracts">{source-stencil-guid}</SourceGuid>
<SourceX xmlns="...Abstracts">0</SourceX>
<SourceY xmlns="...Abstracts">0</SourceY>
<TargetGuid xmlns="...Abstracts">{target-stencil-guid}</TargetGuid>
<TargetX xmlns="...Abstracts">0</TargetX>
<TargetY xmlns="...Abstracts">0</TargetY>
</a:Value>
</a:KeyValueOfguidanyType>
```
## Property attribute types
Properties use typed `<a:anyType>` elements:
| `i:type` | Purpose | Value |
|----------|---------|-------|
| `b:HeaderDisplayAttribute` | Section header | `i:nil="true"` |
| `b:StringDisplayAttribute` | Text value (Name, Reason) | `i:type="c:string"` |
| `b:BooleanDisplayAttribute` | Boolean (Out Of Scope) | `i:type="c:boolean"` |
| `b:ListDisplayAttribute` | Dropdown list | Has `<b:SelectedIndex>` |
## Threat instances
Threats go in `<ThreatInstances>` using `<a:KeyValueOfstringThreatpc_P0_PhOB>` (note the exact
`PhOB` suffix). Unlike stencils, the threat `<a:Value>` fields are **`b:`-prefixed** (the
`ThreatModeling.KnowledgeBase` namespace), and the `<a:Key>` is the literal concatenation
`TH<id> + <SourceGuid> + <FlowGuid> + <TargetGuid>`:
```xml
<ThreatInstances xmlns:a="...Arrays">
<a:KeyValueOfstringThreatpc_P0_PhOB>
<a:Key>TH117{source-guid}{flow-guid}{target-guid}</a:Key>
<a:Value xmlns:b="...KnowledgeBase">
<b:ChangedBy/>
<b:DrawingSurfaceGuid>{drawing-surface-guid}</b:DrawingSurfaceGuid>
<b:FlowGuid>{flow-guid}</b:FlowGuid>
<b:Id>32</b:Id>
<b:InteractionKey>{source-guid}:{flow-guid}:{target-guid}</b:InteractionKey>
<b:InteractionString i:nil="true"/>
<b:ModifiedAt>2025-01-01T00:00:00</b:ModifiedAt>
<b:Priority>High</b:Priority>
<b:Properties>
<a:KeyValueOfstringstring>
<a:Key>Title</a:Key>
<a:Value>An adversary may spoof the user and gain access</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>UserThreatCategory</a:Key>
<a:Value>Spoofing</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>UserThreatShortDescription</a:Key>
<a:Value>Spoofing is when a process or entity is something other than its claimed identity.</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>PossibleMitigations</a:Key>
<a:Value>Enable multi-factor authentication and least-privilege access control.</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>Priority</a:Key>
<a:Value>High</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>SDLPhase</a:Key>
<a:Value>Design</a:Value>
</a:KeyValueOfstringstring>
</b:Properties>
<b:SourceGuid>{source-stencil-guid}</b:SourceGuid>
<b:State>Mitigated</b:State>
<b:StateInformation i:nil="true"/>
<b:TargetGuid>{target-stencil-guid}</b:TargetGuid>
<b:Title i:nil="true"/>
<b:TypeId>TH117</b:TypeId>
<b:Upgraded>false</b:Upgraded>
<b:Wide>false</b:Wide>
</a:Value>
</a:KeyValueOfstringThreatpc_P0_PhOB>
</ThreatInstances>
```
**Every GUID must resolve:** `SourceGuid` and `TargetGuid` must equal `<a:Key>` values of real
stencils in `<Borders>`, and `FlowGuid` must equal the `<a:Key>` of a real connector in
`<Lines>`. Dangling references produce a model that opens with missing diagram elements.
Use the standard STRIDE categories for `UserThreatCategory`: **S**poofing, **T**ampering,
**R**epudiation, **I**nformation Disclosure, **D**enial of Service, **E**levation of Privilege.
## Common mistakes that break TM7 files
1. **Adding an `<?xml version="1.0"?>` declaration**`DataContractSerializer` does not emit one.
2. **Using `xmlns:xsi` / `xmlns:xsd`** instead of DataContract namespaces.
3. **Using simple element names** like `<Border>`, `<Line>`, `<Stencil>` — you must use the
DataContract wrapper types such as `<a:KeyValueOfguidanyType>`.
4. **Inventing elements the tool never emits** like `<SecurityGaps>` or `<Mitigations>` — these
are not in the schema. (`<MetaInformation>`, `<Notes>`, and `<KnowledgeBase>` **are** valid
and must be preserved.)
5. **Using human-readable GUIDs** like `users-browser` instead of real UUIDs
(e.g. `148ade68-5c80-40f3-8e1f-4e2cabdb5991`).
6. **Dangling references** — a `Line`, threat `SourceGuid`/`TargetGuid`, or threat `FlowGuid`
that points to a stencil/flow GUID that isn't actually defined in `<Borders>`/`<Lines>`.
Every reference must resolve to an included element.
7. **Missing or duplicated `z:Id` reference attributes** — every serialized object needs a
`z:Id`, and each `z:Id` (e.g. `i1`, `i2`, `i10`) must be **unique** across the whole file.
When you duplicate a template block to add an element, always renumber its `z:Id` (and any
nested ones) to values not used elsewhere; reusing an id creates duplicate DataContract
object ids and makes deserialization fail.
8. **Missing the `xmlns` on child elements** — each `GenericTypeId`, `Guid`, `Properties`,
`TypeId`, etc. must carry its own
`xmlns="http://schemas.datacontract.org/2004/07/ThreatModeling.Model.Abstracts"`.
9. **Pretty-printing with indentation** — the correct output is a single continuous XML stream
with no added newlines or indentation inside the content.
## Reference asset
Always use [`assets/example-minimal.tm7`](./assets/example-minimal.tm7) in this skill's
directory as the structural reference. It is a fully synthetic, sanitized export (no personal or
project data) that opens cleanly in the tool: two stencils connected by one data flow, with one
STRIDE threat whose every reference resolves. Adapt the stencil types, names, properties,
coordinates, data flows, and threats to the user's architecture, but **never** change the
serialization format or namespace structure, and only use stencil `TypeId` values that already
appear in its bundled `KnowledgeBase`. After generating, mentally diff your output's skeleton
against the example to confirm every namespace, wrapper element, and GUID reference matches.
File diff suppressed because one or more lines are too long