The data model
The model is YAML on disk, validated against JSON Schema, and published as JSON. An assessment is a separate document with its own schema, so a tool can validate one before scoring it.
Layout
model/
meta.yaml levels, domain weights, tiers and entry gates,
the five integrity constraints, applicability
profiles, environment archetypes
domains/*.yaml one file per domain: sub-capabilities, weights,
profiles, questions, six level descriptors,
evidence criteria, crosswalks
schema/
model.schema.json validates the model itself
assessment.schema.json validates an assessment document
data/
attack_techniques.csv 697 techniques with tactics and platforms
attack_actors.csv 1,057 actors with the techniques each uses
attack_analytics.json 1,745 analytics with required log sources
attack_detection.csv detection strategies per technique
attack_log_sources.csv normalised log source index
telemetry_catalogue.yaml how to enable each source
A sub-capability
- id: AV.3
name: Threat-actor emulation plans
weight: 14
profile: standard
question: >-
...
levels:
0: ...
5: ...
evidence:
- Named artefact that substantiates a claim at 4 or 5
crosswalk:
nist_csf_2: [DE.CM-01, ID.RA-05]
soc_cmm: [Process.Use case management]
Scoring an assessment
The arithmetic is specified in full on the scoring page. Implement the specification and you can reproduce the arithmetic; conformance vectors — complete assessments with the scores a conforming implementation must produce — are not yet published and may accompany a future release.
Crown-jewel asset types
A crown jewel’s cat is one of the nine legacy categories (identity,
data, cloud, code, backup, endpoint,
email, ot, other) or one of the sixteen asset types added with model 1.6.0. A legacy value behaves exactly as it always has. An asset type contributes its own tactic
weights to the likely-attack ranking (the impact term is multiplied by 1 + weight for the
technique’s worst tactic; the exposure formula is unchanged), maps to a legacy category for
compatibility, and to a TIR-CMM asset class for the export.
| Asset type | Legacy category | Tactic weights (impact multiplier) |
|---|---|---|
Identity and privileged access identity-access | identity | Credential Access ×2.0, Lateral Movement ×1.9, Privilege Escalation ×1.9, Persistence ×1.6, Defense Impairment ×1.5 |
Business and operational data business-data | data | Collection ×2.0, Exfiltration ×2.0, Impact ×1.7, Discovery ×1.4 |
Web applications web-app | other | Initial Access ×2.0, Persistence ×1.8, Collection ×1.7, Exfiltration ×1.7, Impact ×1.6 |
APIs and integrations api | other | Initial Access ×1.9, Collection ×1.8, Exfiltration ×1.8, Credential Access ×1.7, Impact ×1.5 |
Mobile applications and mobile backends mobile-backend | other | Initial Access ×1.8, Credential Access ×1.8, Collection ×1.7, Exfiltration ×1.7 |
SaaS and collaboration platforms saas-collab | other | Collection ×1.9, Initial Access ×1.8, Credential Access ×1.8, Exfiltration ×1.8, Persistence ×1.6 |
Email services email-services | email | Initial Access ×2.0, Collection ×1.9, Exfiltration ×1.7, Credential Access ×1.6 |
Cloud workloads cloud-workload | cloud | Privilege Escalation ×1.9, Persistence ×1.8, Exfiltration ×1.8, Impact ×1.7, Initial Access ×1.6 |
End-user endpoints endpoint-fleet | endpoint | Execution ×1.8, Persistence ×1.7, Defense Impairment ×1.7, Impact ×1.6 |
Servers and data centres servers-dc | other | Execution ×1.8, Persistence ×1.8, Lateral Movement ×1.8, Privilege Escalation ×1.7, Impact ×1.7 |
Network and perimeter infrastructure network-perimeter | other | Initial Access ×1.9, Command and Control ×1.8, Defense Impairment ×1.7, Lateral Movement ×1.6, Discovery ×1.5 |
Source code, repositories and CI/CD source-cicd | code | Initial Access ×1.9, Persistence ×1.9, Collection ×1.7, Impact ×1.7 |
Data platforms and databases data-platform | data | Collection ×2.0, Exfiltration ×2.0, Impact ×1.7, Discovery ×1.4 |
Backups and recovery systems backup-recovery | backup | Impact ×2.0, Defense Impairment ×1.8, Discovery ×1.4 |
OT, ICS and IoT ot-ics-iot | ot | Impact ×2.0, Lateral Movement ×1.7, Persistence ×1.6 |
Other / custom critical service custom | other | none |
email keeps its rule: class A4 when a SaaS suite is declared, otherwise A3. The
platform, telemetry-family, class and template columns are on the threat-scope page.
Detection and scenario registers
Since model 1.6.0 a saved assessment may carry four optional members. All are absent from files
saved earlier, default when absent, and change no maturity result: det, an object keyed
by technique id; scen, an array of scenarios; lens, the frameworks ticked
for the standards lens; and detWindow, the stated validation recency window in days
(30–730, default 180). A file saved before these existed also has its step index
remapped, so “results” is still results.
det["T1003.001"]: {name, rule, deployed (yes|no), enabled (yes|no),
health (healthy|degraded|failed|unknown), healthDate (YYYY-MM-DD), dest, owner,
valDate (YYYY-MM-DD), valMethod (atomic|emulation|purple|bas|production-tp|other),
outcome (fired|fired-late|not-fired), artefact, notes, cls (D|C|H), intent (gap|by-design)}
scen[]: {id "SC-n", name, objective, jewel, actor, window, testDate, method, artefact, result, notes,
steps[]: {t (technique id), stage (S1..S7), entities, vis (observed|inferred|hypothesised),
det (detected|not-detected|"" = from register), val (fired|not-fired|"" = from register),
keys[] (identity|host|process|session|cloud-principal|ip|workload|app-trace|api-request|case-id),
join (yes|no), note}}
Every value passes the same sanitiser as the rest of the file: unknown technique ids, stages, states
and keys are dropped, strings are bounded, dates must be ISO dates. Provenance is never read from the
file. The derived status per technique (0–3 or not assessed) is computed on load from the
register and the telemetry reach, in this order: no deployed answer → not assessed (whatever the
telemetry reach); an answer with required telemetry reach of 0% → 0; then 1–3 from the
evidence. It is not stored, so it cannot be imported. valMethod values
atomic, emulation, purple, bas, red-team
and pentest qualify for status 3; production-tp and other are kept
as recorded and stay at 2.
CSV register format. The detection step exports and imports a CSV with a header row
and these columns, in this order; unknown columns are ignored, unknown technique ids and values are
dropped, and derived_status is written on export and never read:
technique_id,technique_name,tier,detection_name,rule_id,deployed,enabled,telemetry_health,health_checked,alert_destination,owner,validated_on,validation_method,outcome,artefact,class,intent,notes,derived_status
The columns are the Detection register tab of the workbook, column for column, so a
register kept in a spreadsheet can be brought in. (The workbook’s ATT&CK Coverage
tab is the older technique-status list and is not the import format.)
The TIR-CMM export
Changed with model 1.6.0, without breaking the contract.
in_scope_techniques[].status may now be 2 or 3, but only where the detection register
holds the evidence the model requires: 2 for a deployed, enabled detection with healthy required
telemetry and a named artefact; 3 when a validation with a recorded method and a fired outcome falls
inside the stated recency window. A technique without a detection answer keeps the reach-based 0 or 1,
so an assessment with no register produces the same export it always did. Registered scenarios are appended
to attack_paths as SC-n entries in the contract’s own shape, with a
note stating their status under the Scenario Coverage Score rule. A crown jewel with an asset type
carries asset_type beside its legacy tid_cmm_category. The published export
schema was relaxed accordingly (status maximum 1 → 3, optional asset_type); TIR-CMM’s
import contract already permitted 0–3 and is unchanged. No narrative field was added.
TIR-CMM is the response module of UTIOM: TID-CMM asks
whether you would see the adversary, TIR-CMM whether you could stop them.
The assessment tool writes a document for that handoff. It satisfies TIR-CMM’s
import contract and is
validated by /api/tid-cmm-export.schema.json,
which is that contract plus provenance. Every field but the schema tag is optional, because an
assessment that has scoped but not yet scored is still worth handing over.
TID-CMM 1.6.0 produces tid-cmm/export/1.0. TIR-CMM 1.0 can import the core
handoff context it recognises: the constrained detection score, the crown jewels with their asset classes,
the adversaries by name, and the stage and asset-class scope of the attack paths. The export retains
additional TID-CMM 1.6 assessment detail — asset types, crown-jewel impact and rationale, actor
identifiers, the per-technique register with its statuses, evidence and mitigations, scenario identity and
technique membership, the constraint log, the domain results and the scope block — but the current
TIR-CMM importer does not yet consume every extended field. Scenario step order does not survive the handoff:
a scenario arrives as the set of stages it touches, not as a sequence. The fields below describe what the
document carries, not what any one consumer reads.
| Field | What it carries |
|---|---|
schema | tid-cmm/export/1.0. The published import
contract permits any tag beginning tid-cmm/export/. |
detection_score_pre_substitution | The constrained overall
(C1–C5 applied in strict mode) before any TIR-CMM result is substituted into
the IR domain. TIR-CMM reads it as D for its constraint R4, which caps response,
containment and forensics at D + 1. Asking for the pre-substitution figure
is what stops the two models inflating each other in a loop. The browser tool performs no
substitution today, so overall carries the same number and
ir_substitution says none. |
domains, domains_raw, overall_raw,
constraint_log | The constrained domain scores, the self-assessed ones, and every constraint that moved a number, as reported on the results page. |
crown_jewels[] | Each declared jewel with its TIR-CMM asset classes (table below), plus the TID-CMM category and impact band it was declared with. |
actors[] | The prioritised adversaries by ATT&CK id and name.
No breakout_minutes: TID-CMM holds no tempo data, TIR-CMM supplies its own. |
attack_paths[] | Derived, not declared — see below. |
in_scope_techniques[] | Every technique in scope with its tier, its Validated Coverage status, the telemetry reach and assurance band behind that status, and the ATT&CK mitigation ids for the technique. |
generator, depth, strict,
actor_provenance, notes[] | Model version, tool build, assessment depth, whether constraints were applied, how the adversary set was arrived at, and the derivations written out in prose so the file explains itself. |
What the export will and will not claim
Status is telemetry-derived 0 or 1 unless the register evidences more. The
Validated Coverage scale runs 0 (no telemetry), 1 (telemetry only), 2 (detection logic exists),
3 (validated by emulation). The browser tool computes telemetry reach from the log sources
ATT&CK’s analytics require and writes 0 or 1 from it. It writes 2 only where the
detection register holds a deployed, enabled detection with healthy required telemetry and a
named artefact, and 3 only where a qualifying controlled adversarial validation (atomic test,
adversary emulation, purple team, BAS, red team, or an evidenced penetration test) with a fired
outcome falls inside the stated recency window; a production true positive or an unreviewed
method stays at 2. A technique without a register answer keeps its telemetry-derived status:
exported telemetry status and detection-register completeness are two different
readings, and the file’s notes say which applies. For an assessment
with no detection evidence the note reads: “No per-technique detection evidence was
recorded in this assessment, so technique statuses in this payload remain telemetry-derived 0
or 1. The tool exports status 2 or 3 only where the detection register contains the required
evidence.” visibility_percent and assurance travel alongside so
nothing that was computed is lost. A technique with no ATT&CK analytic has no status at all:
reach cannot be computed for it, which is not the same as blind.
Attack paths are derived. TID-CMM’s attack-path step marks Tier A
techniques — on a modelled path to a crown jewel — and does not draw per-actor
paths against named assets. The export builds one path per selected actor from the Tier A
techniques that actor is documented using. Its stages come from those techniques’
tactics through the table below; its asset classes are the union of the declared crown
jewels, because TID-CMM does not tie a technique to a single jewel. Tier A techniques no
selected actor is documented using travel as one unattributed path. The file says all of
this in its notes.
Mappings
| TID-CMM crown-jewel category | TIR-CMM asset class |
|---|---|
| Identity / Active Directory | A1 Identity & Access Infrastructure |
| Endpoint fleet | A2 Endpoint & User Compute |
| Cloud account / control plane | A4 Cloud Control Plane & SaaS |
| Email / collaboration | A4 when Microsoft 365 or Google Workspace is declared; otherwise A3 Server & Datacentre Workload — mail you host yourself |
| Source code / build pipeline | A6 Application, Source & CI/CD |
| Database / data store | A7 Data Stores & Backup |
| Backups / recovery | A7 Data Stores & Backup |
| OT / ICS / physical process | A8 OT / ICS / IoT & Specialist |
| Other / not sure | none |
| ATT&CK tactic | TIR-CMM attack-path stage |
|---|---|
| Reconnaissance, Resource Development | S0 Prevent & Harden — pre-intrusion, where architecture can still stop it |
| Initial Access | S1 Initial Access & Foothold |
| Execution, Persistence, Stealth, Defense Impairment | S2 Execution & Persistence — the response question at that stage is whether the foothold can be killed and kept from returning |
| Privilege Escalation, Credential Access | S3 Privilege Escalation & Credential Access |
| Discovery, Lateral Movement | S4 Discovery & Lateral Movement |
| Collection | S5 Collection & Staging |
| Command and Control, Exfiltration | S6 Command & Control and Exfiltration |
| Impact | S7 Impact & Objective |
Both tables are judgements and are exposed here so they can be argued with. Neither changes a TID-CMM score.
A fragment
{
"schema": "tid-cmm/export/1.0",
"generator": { "model_version": "1.6.0", "tool_build": "2026-09-07", ... },
"assessed_at": "2026-08-10",
"depth": "structured", "strict": true, "actor_provenance": "reviewed",
"detection_score_pre_substitution": 2.37,
"overall": 2.37, "overall_raw": 2.43, "ir_substitution": "none",
"domains": { "TI": 3, "TM": 1, "DC": 2, "DE": 2, ... },
"constraint_log": [ "C4: DC 3.00 exceeds max(TI,TM)+1; capped to 2.00.", ... ],
"crown_jewels": [ { "id": "CJ-1", "name": "Core banking database",
"asset_classes": ["A7"], "tid_cmm_category": "data", "impact": "high" } ],
"actors": [ { "id": "G0102", "name": "Wizard Spider", "kind": "group" } ],
"attack_paths": [ { "id": "AP-G0102", "actor": "G0102",
"stages": ["S1","S2","S3","S4","S7"], "asset_classes": ["A1","A7"],
"techniques": ["T1003.001", "T1021.001", ...] } ],
"in_scope_techniques": [ { "id": "T1003.001", "tier": "A", "status": 1,
"visibility_percent": 92, "assurance": "assured",
"mitigations": ["M1015", "M1026", "M1027", ...] }, ... ],
"notes": [ "detection_score_pre_substitution is the constrained TID-CMM overall ...", ... ]
}