MITRE ATT&CK Coverage

Complete

Overview

The MITRE ATT&CK Coverage module gives SOC teams a visual, interactive view of which adversary tactics and techniques the ThreatOps detection rule library currently covers. In a managed security operations service, customers and analysts need to answer a single critical question: which attack paths can we detect today? Without this visibility, coverage gaps remain invisible until an attacker exploits them.

This module maps every active detection rule's mitre_tactic and mitre_technique_id fields against all 12 MITRE ATT&CK Enterprise tactics (TA0001–TA0040) and their representative techniques, producing a real-time heat-map matrix, per-tactic progress bars, an overall coverage score, and a prioritized gap analysis with actionable recommendations. It is directly driven by the 372 detection rules in platform/api/app/rules/.

What Was Proposed

What's Built

FeatureStatus
12-tactic ATT&CK matrix (TA0001–TA0040)✓ Complete
Per-tactic coverage progress bars with color thresholds✓ Complete
Overall coverage score card (full / partial / uncovered counts)✓ Complete
Interactive technique cells with click-to-drill-down modal✓ Complete
Technique detail modal listing mapped detection rules with severity badges✓ Complete
Live rule ingestion via GET /api/v1/detection-rules/?limit=1000✓ Complete
Graceful fallback to deterministic mock data when API is unavailable✓ Complete
Gap analysis section sorted by risk severity (critical → low)✓ Complete
Actionable recommendations per gap with Lightbulb icon✓ Complete
Matrix coverage legend (full / partial / no coverage)✓ Complete
Recalculate button for on-demand refresh✓ Complete
Dedicated MITRE-specific backend router⚠ Not needed — uses detection-rules router
Framework export for compliance reporting⚠ Not yet built
Design note: There is no dedicated mitre.py backend router. Coverage is computed entirely on the frontend by consuming GET /api/v1/detection-rules/ and grouping rules by their mitre_tactic field. This keeps the module stateless and always in sync with the live rule library without requiring any additional database queries or backend services.

Architecture

Coverage Computation Pipeline

The coverage calculation runs client-side in src/app/mitre-coverage/page.tsx inside the fetchData useCallback hook, executing three steps on every recalculation:

  1. Rule Fetch — Calls GET /api/v1/detection-rules/?limit=1000 via the shared api client (src/lib/api-client.ts). Handles three API response shapes: plain array, { items: [...] }, and { data: [...] }.
  2. Coverage Mapping — For each of the 12 MITRE tactics, filters rules where rule.mitre_tactic (case-insensitive) matches the tactic name. Techniques are then scored: more than 2 matching rules marks a technique as full; 1–2 rules as partial; zero rules as none.
  3. Score Calculation — Overall coverage percent uses the weighted formula ((full_count + partial_count × 0.5) / total_techniques) × 100. Identical formula is applied per-tactic for the progress bars.

When the API call fails or returns zero rules, the page falls back to generateMockCoverage() and generateMockGaps(), displaying an amber warning banner. This ensures the UI remains fully functional during development or connectivity issues.

Detection Rule Backend Integration

Detection rules exist in two stores, both surfaced by the same API endpoint:

The coverage page queries both sources through the same endpoint, so library rules and tenant-specific rules both contribute to the ATT&CK heat-map.

Gap Analysis

The gap analysis section uses a curated static list of eight high-signal technique gaps representing the most commonly exploited and under-detected attack patterns in enterprise environments:

Tactics & Techniques Covered

The module covers all 12 MITRE ATT&CK Enterprise tactics. Each tactic maps to a technique bank of 4–7 representative techniques drawn from the most prevalent sub-techniques in each category:

Tactic IDTactic NameTechnique CountSample Techniques
TA0001Initial Access6Phishing, Valid Accounts, Exploit Public-Facing App, External Remote Services, Drive-by Compromise, Supply Chain Compromise
TA0002Execution6Command & Scripting Interpreter, PowerShell, WMI, Scheduled Task/Job, User Execution, Native API
TA0003Persistence6Boot/Logon Autostart, Create Account, Scheduled Task/Job, Registry Run Keys, Browser Extensions, Office App Startup
TA0004Privilege Escalation5Access Token Manipulation, Exploitation for Priv Esc, Process Injection, Sudo Caching, Abuse Elevation Control
TA0005Defense Evasion7Obfuscated Files, Masquerading, Indicator Removal, Process Injection, Rootkit, Signed Binary Proxy, Virtualization Evasion
TA0006Credential Access6Brute Force, OS Credential Dumping, Credentials from Password Stores, Steal Web Session Cookie, Kerberoasting, Input Capture
TA0007Discovery6System Information Discovery, Account Discovery, Network Service Discovery, Permission Groups Discovery, Process Discovery, Remote System Discovery
TA0008Lateral Movement5Remote Services, Lateral Tool Transfer, RDP, SMB/Windows Admin Shares, Exploitation of Remote Services
TA0009Collection5Data from Local System, Screen Capture, Clipboard Data, Email Collection, Archive Collected Data
TA0011Command & Control6Application Layer Protocol, Encrypted Channel, Proxy, Ingress Tool Transfer, Non-Standard Port, Web Service
TA0010Exfiltration4Exfiltration Over Web Service, Over C2 Channel, Automated Exfiltration, Over Alternative Protocol
TA0040Impact5Data Encrypted for Impact, Service Stop, Inhibit System Recovery, Account Access Removal, Defacement

API Endpoints

The MITRE Coverage module does not have a dedicated backend router. It relies entirely on the Detection Rules API, which exposes MITRE tactic and technique metadata on every rule record.

Detection Rules API (consumed by this module)

Router file: platform/api/app/routers/detection_rules.py — Prefix: /api/v1/detection-rules

GET  /api/v1/detection-rules/?limit=1000

Query parameters used by coverage page:
  limit=1000   # Fetch all rules in a single request

Response fields consumed by coverage computation:
  id                  string   Rule UUID
  name                string   Human-readable rule name
  severity            string   critical / high / medium / low
  mitre_tactic        string?  ATT&CK tactic name (e.g. "Initial Access")
  mitre_technique_id  string?  ATT&CK technique ID (e.g. "T1566")
  enabled             boolean  Whether the rule is active

Response Shape Handling

The frontend handles multiple API response shapes to accommodate both the library and DB-backed rules endpoints:

// All three shapes are supported:
rulesRes               // Plain array
rulesRes.items         // Paginated response { items: [...] }
rulesRes.data          // Alternative envelope { data: [...] }

Frontend Routes

LayerPathDescription
/mitre-coverageNext.js App Router page — main ATT&CK coverage UI
/api/v1/detection-rules/Backend endpoint consumed for live rule-to-coverage mapping

Frontend Page File

File: platform/frontend/src/app/mitre-coverage/page.tsx

The page is a single React client component ('use client') with two primary state objects: tacticCoverage (a Record<string, TacticCoverage> keyed by tactic ID) and gaps (the prioritized gap list). A single fetchData callback populates both on mount and on manual recalculation. The selectedTechnique state drives the detail modal visibility.

Data Model

The MITRE Coverage module is stateless on the backend — there is no dedicated database table. All coverage data is computed in-memory on the frontend from the detection rule records. The relevant TypeScript types are defined at the top of page.tsx:

TacticCoverage

FieldTypeDescription
tactic_idstringMITRE tactic ID (e.g. "TA0001")
tactic_namestringTactic display name (e.g. "Initial Access")
total_techniquesnumberTotal techniques in the bank for this tactic
covered_techniquesnumberCount of fully covered techniques
partial_techniquesnumberCount of partially covered techniques
coverage_percentnumberWeighted score: (full + partial×0.5) / total × 100, rounded to integer
techniquesTechniqueCoverage[]Array of technique-level coverage details

TechniqueCoverage

FieldTypeDescription
technique_idstringATT&CK technique ID (e.g. "T1566")
technique_namestringTechnique display name
coverage'full' | 'partial' | 'none'Coverage classification: full (>2 rules), partial (1–2 rules), none (0 rules)
rule_countnumberNumber of detection rules mapped to this technique
rules{ id, name, severity }[]Up to 5 detection rules shown in the drill-down modal

GapItem

FieldTypeDescription
technique_idstringATT&CK technique ID (e.g. "T1566")
technique_namestringTechnique name
tactic_namestringParent tactic name
risk_severity'critical' | 'high' | 'medium' | 'low'Analyst-assigned risk classification for missing coverage
recommendationstringActionable guidance for closing the coverage gap

Detection Rule (MITRE fields — from backend)

Model: platform/api/app/models/detection_rule.py — Table: detection_rules

ColumnTypeDescription
mitre_tacticStringSingle tactic name string. Normalized from mitre_tactics[0] for library rules. Used for coverage grouping.
mitre_technique_idStringSingle technique ID string. Normalized from mitre_techniques[0] for library rules. Used for technique-level mapping.

UI Layout

Page Structure

The page is contained in a max-w-7xl mx-auto wrapper and divided into five vertical sections rendered top-to-bottom:

  1. Header — Orange Grid3X3 icon in a rounded-lg tile, "MITRE ATT&CK Coverage" title, subtitle text, and a "Recalculate" button that re-calls fetchData.
  2. Stats Row — 4-column grid of metric cards: Overall Coverage % with a color-coded progress bar (green ≥70%, yellow 40–69%, red <40%); Fully Covered count (green background); Partial Coverage count (yellow background); Uncovered Gaps count (red background).
  3. Per-Tactic Progress Bars — A 2-column grid inside a white card, one row per tactic. Each row shows the tactic name truncated to 144px, a flex-grow colored progress bar, and the percentage value.
  4. ATT&CK Matrix Grid — Horizontal CSS grid with one column per tactic (minmax(100px, 1fr)). Tactic headers show the tactic name in 10px bold uppercase and a covered/total fraction. Below the headers, each technique renders as a small color-coded button cell: bg-green-500 (full), bg-yellow-400 (partial), bg-slate-200 (none). Clicking any cell sets selectedTechnique state and opens the modal.
  5. Gap Analysis — A list of GapItem rows, each showing: a risk severity badge, the technique ID and name in bold, the parent tactic name in muted gray, and a lightbulb icon followed by the recommendation string.

Technique Detail Modal

Triggered by clicking any matrix cell. Renders as a fixed full-viewport overlay with a centered white card (max-w-lg). Contents:

Modal closes on clicking the backdrop or the X icon button.

Prerequisites