TID-CMM Threat-Informed Detection Capability Maturity Model
Home › Developers › Data model

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.

The repository

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 typeLegacy categoryTactic weights (impact multiplier)
Identity and privileged access identity-accessidentityCredential Access ×2.0, Lateral Movement ×1.9, Privilege Escalation ×1.9, Persistence ×1.6, Defense Impairment ×1.5
Business and operational data business-datadataCollection ×2.0, Exfiltration ×2.0, Impact ×1.7, Discovery ×1.4
Web applications web-appotherInitial Access ×2.0, Persistence ×1.8, Collection ×1.7, Exfiltration ×1.7, Impact ×1.6
APIs and integrations apiotherInitial Access ×1.9, Collection ×1.8, Exfiltration ×1.8, Credential Access ×1.7, Impact ×1.5
Mobile applications and mobile backends mobile-backendotherInitial Access ×1.8, Credential Access ×1.8, Collection ×1.7, Exfiltration ×1.7
SaaS and collaboration platforms saas-collabotherCollection ×1.9, Initial Access ×1.8, Credential Access ×1.8, Exfiltration ×1.8, Persistence ×1.6
Email services email-servicesemailInitial Access ×2.0, Collection ×1.9, Exfiltration ×1.7, Credential Access ×1.6
Cloud workloads cloud-workloadcloudPrivilege Escalation ×1.9, Persistence ×1.8, Exfiltration ×1.8, Impact ×1.7, Initial Access ×1.6
End-user endpoints endpoint-fleetendpointExecution ×1.8, Persistence ×1.7, Defense Impairment ×1.7, Impact ×1.6
Servers and data centres servers-dcotherExecution ×1.8, Persistence ×1.8, Lateral Movement ×1.8, Privilege Escalation ×1.7, Impact ×1.7
Network and perimeter infrastructure network-perimeterotherInitial 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-cicdcodeInitial Access ×1.9, Persistence ×1.9, Collection ×1.7, Impact ×1.7
Data platforms and databases data-platformdataCollection ×2.0, Exfiltration ×2.0, Impact ×1.7, Discovery ×1.4
Backups and recovery systems backup-recoverybackupImpact ×2.0, Defense Impairment ×1.8, Discovery ×1.4
OT, ICS and IoT ot-ics-iototImpact ×2.0, Lateral Movement ×1.7, Persistence ×1.6
Other / custom critical service customothernone

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.

FieldWhat it carries
schematid-cmm/export/1.0. The published import contract permits any tag beginning tid-cmm/export/.
detection_score_pre_substitutionThe 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_logThe 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 categoryTIR-CMM asset class
Identity / Active DirectoryA1 Identity & Access Infrastructure
Endpoint fleetA2 Endpoint & User Compute
Cloud account / control planeA4 Cloud Control Plane & SaaS
Email / collaborationA4 when Microsoft 365 or Google Workspace is declared; otherwise A3 Server & Datacentre Workload — mail you host yourself
Source code / build pipelineA6 Application, Source & CI/CD
Database / data storeA7 Data Stores & Backup
Backups / recoveryA7 Data Stores & Backup
OT / ICS / physical processA8 OT / ICS / IoT & Specialist
Other / not surenone
ATT&CK tacticTIR-CMM attack-path stage
Reconnaissance, Resource DevelopmentS0 Prevent & Harden — pre-intrusion, where architecture can still stop it
Initial AccessS1 Initial Access & Foothold
Execution, Persistence, Stealth, Defense ImpairmentS2 Execution & Persistence — the response question at that stage is whether the foothold can be killed and kept from returning
Privilege Escalation, Credential AccessS3 Privilege Escalation & Credential Access
Discovery, Lateral MovementS4 Discovery & Lateral Movement
CollectionS5 Collection & Staging
Command and Control, ExfiltrationS6 Command & Control and Exfiltration
ImpactS7 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 ...", ... ]
}