Advanced โฑ 150 min ๐Ÿ“‹ 10 Steps

Integrate DVM with Threat Intelligence & Risk Analytics

Correlate vulnerability data with active threat campaigns, exploit intelligence, and MITRE ATT&CK techniques. Build threat-informed remediation priorities, create risk analytics dashboards, and design a threat-informed vulnerability management program.

๐Ÿ“‹ Overview

About This Lab

Threat intelligence integration transforms vulnerability management from a score-based prioritisation exercise into a threat-informed defence strategy. By correlating DVM data with active threat campaigns, exploit intelligence, and risk analytics, you can focus remediation on the vulnerabilities that attackers are actually exploiting today. not just those with high CVSS scores.

๐Ÿข Enterprise Use Case

A security team faces 15,000 CVEs across their estate but can only patch 200 per week. By integrating threat intelligence, they identify 45 CVEs actively exploited in the wild by threat actors targeting their industry. These 45 become the immediate priority, reducing real-world risk by 80% in the first remediation cycle.

๐ŸŽฏ What You Will Learn

  1. Understand DVM threat intelligence integration
  2. Review exploit predictions and active exploit data
  3. Identify vulnerabilities in active threat campaigns
  4. Correlate vulnerabilities with MITRE ATT&CK techniques
  5. Build threat-informed remediation priorities
  6. Configure event timeline for vulnerability exploitation
  7. Create risk analytics dashboards
  8. Use Advanced Hunting for vulnerability-threat correlation
  9. Generate threat-informed risk reports
  10. Design a threat-informed vulnerability management program

๐Ÿ”‘ Why This Matters

Only 5% of CVEs are ever exploited in the wild. Patching based on CVSS scores alone wastes resources on vulnerabilities that will never be attacked. Threat intelligence focuses your limited remediation capacity on the vulnerabilities that matter most.

โš™๏ธ Prerequisites

  • Licensing: Microsoft Defender Vulnerability Management add-on or Defender for Endpoint P2; Microsoft Defender Threat Intelligence (MDTI) for enriched TI data
  • Roles: Security Administrator for threat analytics access; Security Reader for vulnerability and TI data queries
  • Data Sources: Threat analytics reports enabled in Defender XDR portal; DeviceTvmSoftwareVulnerabilities table populated
  • TI Feeds: CISA Known Exploited Vulnerabilities (KEV) catalogue access for Step 4 correlation
  • Portal Access: Microsoft Defender portal (security.microsoft.com) with Advanced Hunting and Threat Analytics
  • Tooling: PowerShell 7+ with Microsoft.Graph module; internet access for CISA KEV API calls

Step 1 ยท Review Exploit Predictions

DVM's exploit prediction engine uses machine learning to assess the likelihood that each CVE will be exploited in the next 30 days. Combined with the "exploit available" flag (indicating a public exploit already exists), this gives you two powerful signals for prioritisation that go far beyond static CVSS scores.

  1. Navigate to Vulnerability management > Weaknesses
  2. Review the Exploit prediction column: High, Medium, Low likelihood
  3. Filter by Exploit available: Yes to see vulnerabilities with known exploits
  4. Focus on vulnerabilities with High exploit prediction + exploit available
// ============================================================
// Exploit Prediction Analysis: Highest-Risk CVEs
// ============================================================
// WHAT: Identifies CVEs in your environment that have both a
//       public exploit AND high exploit prediction likelihood.
// WHY:  These are the CVEs most likely to be used in an attack
//       against your organisation in the next 30 days. They
//       should be your #1 patching priority.
// TABLE: DeviceTvmSoftwareVulnerabilities
DeviceTvmSoftwareVulnerabilities
| where IsExploitAvailable == true
| where VulnerabilitySeverityLevel in ("Critical", "High")
| summarize
    AffectedDevices  = dcount(DeviceId),
    InternetFacing   = dcountif(DeviceId, IsInternetFacing == true),
    AffectedSoftware = make_set(SoftwareName, 3)
    by CveId, VulnerabilitySeverityLevel
| order by AffectedDevices desc
| extend PatchPriority = case(
    InternetFacing > 0 and AffectedDevices > 50,
        "๐Ÿ”ด EMERGENCY - Patch within 24 hours",
    InternetFacing > 0,
        "๐ŸŸ  URGENT - Patch within 72 hours",
    AffectedDevices > 100,
        "๐ŸŸก HIGH - Patch within 7 days",
    "๐ŸŸข STANDARD - Patch within 30 days")
| project PatchPriority, CveId, VulnerabilitySeverityLevel,
          AffectedDevices, InternetFacing, AffectedSoftware
💡 Pro Tip: DVM's exploit prediction is updated daily. A CVE with a "Low" prediction today can jump to "High" overnight when a proof-of-concept exploit is published. Check the prediction column daily, not weekly, for critical CVEs in your environment.

Step 2 ยท Identify Active Threat Campaigns

Threat analytics in Defender XDR provides curated intelligence reports about active threat campaigns, including which CVEs threat actors are actively exploiting. By joining this intelligence with your vulnerability inventory, you can determine whether any active campaign directly threatens your environment - and take pre-emptive action.

  1. Navigate to Threat analytics in the Defender XDR portal
  2. Review active threat campaigns and their targeted vulnerabilities
  3. Cross-reference with your DVM vulnerability inventory
  4. Identify any overlap: vulnerabilities in your estate that are actively targeted
// ============================================================
// Correlate Vulnerabilities with Threat Intelligence Indicators
// ============================================================
// WHAT: Joins DeviceTvmSoftwareVulnerabilities with threat
//       intelligence indicator data to find CVEs in your
//       environment that are associated with known threat actors.
// WHY:  A CVE associated with an active threat campaign is
//       infinitely more urgent than one with no known adversary
//       interest, regardless of CVSS score.
// TABLES: DeviceTvmSoftwareVulnerabilities + ThreatIntelligenceIndicator
let tiCVEs = ThreatIntelligenceIndicator
| where isnotempty(Description)
| where Description matches regex "CVE-\\d{4}-\\d+"
| extend ThreatCVE = extract("(CVE-\\d{4}-\\d+)", 1, Description)
| where isnotempty(ThreatCVE)
| summarize
    ThreatSources = make_set(SourceSystem, 3),
    ThreatTypes   = make_set(ThreatType, 3),
    Confidence    = max(ConfidenceScore)
    by ThreatCVE;
DeviceTvmSoftwareVulnerabilities
| summarize
    AffectedDevices  = dcount(DeviceId),
    InternetFacing   = dcountif(DeviceId, IsInternetFacing == true),
    Severity         = max(VulnerabilitySeverityLevel),
    Software         = make_set(SoftwareName, 3)
    by CveId
| join kind=inner (tiCVEs) on $left.CveId == $right.ThreatCVE
| project CveId, Severity, AffectedDevices, InternetFacing,
          Software, ThreatSources, ThreatTypes, Confidence
| order by AffectedDevices desc
💡 Pro Tip: Not all threat intelligence is equal. Prioritise CVEs associated with threat actors targeting your industry. A CVE used by a financially-motivated group targeting healthcare is far more relevant to a hospital than a CVE used by a nation-state targeting defence contractors.

Step 3 ยท Correlate with MITRE ATT&CK

Mapping vulnerabilities to MITRE ATT&CK techniques creates a bridge between vulnerability management and threat detection. It answers the question: "If this vulnerability is exploited, what can the attacker do next?" This threat-chain thinking helps you prioritise patches that block the most dangerous attack paths, not just the highest CVSS scores.

  1. Map vulnerabilities to MITRE ATT&CK techniques (Initial Access, Privilege Escalation)
  2. Identify which ATT&CK techniques are covered by your current patching
  3. Identify gaps: techniques not addressed by existing remediation activities
  4. Prioritise remediation to close ATT&CK technique coverage gaps
// ============================================================
// Map Exploitable Vulnerabilities to ATT&CK Techniques
// ============================================================
// WHAT: Correlates alerts with known ATT&CK technique IDs and
//       joins with vulnerability data to show which attack
//       techniques your unpatched CVEs enable.
// WHY:  Answering "this CVE enables Privilege Escalation" is
//       far more actionable than "this CVE has CVSS 9.8".
let exploitableVulns = DeviceTvmSoftwareVulnerabilities
| where IsExploitAvailable == true
| where VulnerabilitySeverityLevel in ("Critical", "High")
| summarize
    VulnDevices = dcount(DeviceId),
    CVEs        = make_set(CveId, 5)
    by SoftwareName, SoftwareVersion;
let attackTechniques = AlertInfo
| where Timestamp > ago(30d)
| where isnotempty(AttackTechniques)
| mvexpand todynamic(AttackTechniques)
| extend Technique = tostring(AttackTechniques)
| summarize AlertCount = count(),
            Titles = make_set(Title, 3)
    by Technique;
attackTechniques
| order by AlertCount desc
| project Technique, AlertCount, Titles
| take 20
💡 Pro Tip: Focus your ATT&CK mapping on Initial Access (TA0001), Privilege Escalation (TA0004), and Lateral Movement (TA0008) techniques. Vulnerabilities enabling these tactics create the most dangerous attack chains - they let attackers get in, escalate, and spread.

Step 4 ยท Build Threat-Informed Priorities

CISA's Known Exploited Vulnerabilities (KEV) catalogue is the most authoritative source of CVEs actively exploited in the wild. Federal agencies are required to patch KEV entries within strict timelines, and every organisation should treat this catalogue as a minimum patching standard. This step builds a KQL query that matches your vulnerability inventory against the KEV catalogue to surface CVEs requiring immediate action.

  1. Create a prioritisation matrix: Exploit available + Internet facing + Active campaign = Critical Priority
  2. Rank all vulnerabilities using this threat-informed scoring
  3. Compare with CVSS-only prioritisation to demonstrate the difference
  4. Present the threat-informed priority list to the remediation team
// ============================================================
// CISA KEV Matching: Find Known-Exploited CVEs in Your Estate
// ============================================================
// WHAT: Matches your DVM vulnerability inventory against a
//       reference list of CISA Known Exploited Vulnerabilities.
// WHY:  KEV CVEs are CONFIRMED actively exploited. They are
//       not predictions - they are facts. Any KEV CVE in your
//       environment is a ticking clock.
// SETUP: Populate the kevList with current KEV entries.
//        Download from: https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
//        Or use the externaldata() operator to query live.
// NOTE: Replace the sample CVEs below with your current KEV list
let kevList = dynamic([
    "CVE-2024-21887", "CVE-2024-21893", "CVE-2023-46805",
    "CVE-2024-3400",  "CVE-2024-1709",  "CVE-2024-1708",
    "CVE-2024-27198", "CVE-2023-22515", "CVE-2023-22518",
    "CVE-2023-46747", "CVE-2023-4966",  "CVE-2024-0012",
    "CVE-2024-9474",  "CVE-2023-20198", "CVE-2023-27997"
]);
DeviceTvmSoftwareVulnerabilities
| where CveId in (kevList)
| summarize
    AffectedDevices = dcount(DeviceId),
    InternetFacing  = dcountif(DeviceId, IsInternetFacing == true),
    Severity        = max(VulnerabilitySeverityLevel),
    Software        = make_set(SoftwareName, 3),
    SampleDevices   = make_set(DeviceName, 5)
    by CveId
| extend KEVStatus = "๐Ÿšจ CISA KEV - Confirmed Active Exploitation"
| extend SLA = case(
    InternetFacing > 0, "Patch within 24 hours",
    AffectedDevices > 50, "Patch within 72 hours",
    "Patch within 14 days")
| order by AffectedDevices desc
| project KEVStatus, CveId, Severity, AffectedDevices,
          InternetFacing, SLA, Software, SampleDevices
# ============================================================
# Download and Cache CISA KEV Catalogue for KQL Correlation
# ============================================================
# WHAT: Downloads the live CISA KEV JSON feed and extracts
#       the CVE IDs for use in KQL queries.
# WHY:  Keeps your KEV reference list current without manual
#       updates. The KEV catalogue is updated multiple times
#       per week as new actively-exploited CVEs are added.
# ============================================================

$kevUrl = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
$response = Invoke-RestMethod -Uri $kevUrl -Method Get

# Extract CVE IDs
$kevCVEs = $response.vulnerabilities | Select-Object -ExpandProperty cveID
Write-Host "๐Ÿšจ CISA KEV contains $($kevCVEs.Count) actively exploited CVEs" -ForegroundColor Red

# Format for KQL dynamic list
$kqlList = $kevCVEs | ForEach-Object { "`"$_`"" }
$kqlDynamic = "let kevList = dynamic([`n    " + ($kqlList -join ",`n    ") + "`n]);"

# Save to file for pasting into Advanced Hunting
$kqlDynamic | Out-File -FilePath "C:\Reports\cisa-kev-kql-list.txt" -Encoding UTF8
Write-Host "โœ… KQL kevList saved to C:\Reports\cisa-kev-kql-list.txt" -ForegroundColor Green
Write-Host "   Paste the contents into your Advanced Hunting query" -ForegroundColor Gray
💡 Pro Tip: Automate the KEV download as a daily scheduled task and compare the new list against your DVM inventory. When a new CVE is added to KEV that exists in your environment, send an immediate P0 alert to the patching team. CISA KEV additions mean exploitation is happening right now.

Step 5 ยท Review Event Timeline

DVM's event timeline tracks the lifecycle of every vulnerability: when it was disclosed, when an exploit became available, when threat actors started using it, and when a patch was released. This chronological view lets you assess your exposure window - the time between exploit availability and patch deployment - and set SLAs to shrink it.

  1. Navigate to Vulnerability management > Event timeline
  2. Review recent vulnerability events: new CVEs, new exploits, new threat associations
  3. Set up alerts for new high-priority events affecting your estate
  4. Integrate event timeline data into weekly security briefings
// ============================================================
// Vulnerability Exposure Window Analysis
// ============================================================
// WHAT: Identifies CVEs that have been exploitable in your
//       environment for the longest time without remediation.
// WHY:  The longer a CVE with an exploit sits unpatched, the
//       greater the chance an attacker uses it. Long exposure
//       windows indicate broken patch management processes.
DeviceTvmSoftwareVulnerabilities
| where IsExploitAvailable == true
| where VulnerabilitySeverityLevel in ("Critical", "High")
| summarize
    FirstSeen       = min(Timestamp),
    AffectedDevices = dcount(DeviceId),
    Software        = make_set(SoftwareName, 3)
    by CveId, VulnerabilitySeverityLevel
| extend ExposureDays = datetime_diff('day', now(), FirstSeen)
| where ExposureDays > 30   // Unpatched for over 30 days
| order by ExposureDays desc
| extend ExposureRisk = case(
    ExposureDays > 90, "๐Ÿ”ด CRITICAL - 90+ days unpatched",
    ExposureDays > 60, "๐ŸŸ  HIGH - 60+ days unpatched",
    "๐ŸŸก ELEVATED - 30+ days unpatched")
| project ExposureRisk, CveId, VulnerabilitySeverityLevel,
          ExposureDays, AffectedDevices, Software, FirstSeen
💡 Pro Tip: Use exposure window data to build a "Mean Time to Remediate" (MTTR) metric for your vulnerability management programme. Track MTTR for critical, high, medium, and low severity CVEs separately. Industry best practice targets: Critical โ‰ค 7 days, High โ‰ค 30 days.

Step 6 ยท Create Risk Analytics Dashboards

Risk analytics dashboards are the command centre for threat-informed vulnerability management. They combine vulnerability exposure data with exploit intelligence and threat campaign information into a single view that answers the question every CISO asks: "How much real-world risk do we have right now, and is it going up or down?" This step builds a risk-based remediation workflow query.

// ============================================================
// Risk-Based Remediation Workflow
// ============================================================
// WHAT: Builds a complete remediation priority queue that
//       factors in: severity, exploit availability, internet
//       exposure, fleet impact, and exposure duration.
// WHY:  This is the single query your patch management team
//       should run every morning to decide what to patch today.
// OUTPUT: Ranked CVE list with SLA, affected devices, and
//         recommended remediation action.
DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel in ("Critical", "High")
| summarize
    AffectedDevices = dcount(DeviceId),
    InternetFacing  = dcountif(DeviceId, IsInternetFacing == true),
    ExploitAvail    = max(iff(IsExploitAvailable == true, 1, 0)),
    FirstSeen       = min(Timestamp),
    Software        = make_set(SoftwareName, 3),
    DeviceList      = make_set(DeviceName, 5)
    by CveId, VulnerabilitySeverityLevel
| extend ExposureDays = datetime_diff('day', now(), FirstSeen)
| extend RiskScore =
    (iff(VulnerabilitySeverityLevel == "Critical", 40, 20)) +
    (ExploitAvail * 30) +
    (iff(InternetFacing > 0, 20, 0)) +
    (iff(AffectedDevices > 100, 10, 0))
| extend RemediationSLA = case(
    RiskScore >= 90, "24 hours",
    RiskScore >= 70, "72 hours",
    RiskScore >= 50, "7 days",
    RiskScore >= 30, "14 days",
    "30 days")
| extend Action = case(
    InternetFacing > 0 and ExploitAvail == 1,
        "EMERGENCY PATCH + network isolation until patched",
    ExploitAvail == 1,
        "URGENT PATCH + monitor for exploitation attempts",
    InternetFacing > 0,
        "PRIORITY PATCH + WAF/IPS rule as compensating control",
    "STANDARD PATCH via next maintenance window")
| order by RiskScore desc
| project RiskScore, RemediationSLA, CveId,
          VulnerabilitySeverityLevel, AffectedDevices,
          InternetFacing, ExposureDays, Action, Software
| take 50
// WHAT: Executive summary of vulnerability exposure with threat-informed prioritization
// WHY: Provides a single-view risk dashboard showing total critical/high vulnerabilities
//      broken down by exploitability and internet exposure status.
//      ExploitAvailable = the TRUE priority indicator (not just CVSS score)
// TABLE: DeviceTvmSoftwareVulnerabilities
// KEY FIELDS:
//   VulnerabilitySeverityLevel - Critical | High | Medium | Low (DVM's enriched severity)
//   IsExploitAvailable - true if a public exploit exists (most actionable metric)
//   IsInternetFacing - true if the vulnerable device is exposed to the internet
// OUTPUT: Total vulns, exploitable count, internet-facing count, and high-priority count
DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel in ("Critical", "High")
| summarize TotalVulns = count(),
            ExploitAvailable = countif(IsExploitAvailable == true),
            InternetFacing = countif(IsInternetFacing == true)
| extend HighPriority = ExploitAvailable  // Exploitable = highest priority
| project TotalVulns, ExploitAvailable, InternetFacing, HighPriority
💡 Pro Tip: The remediation workflow query should be the first thing your patch management team runs every morning. Pin it as a shared query in Advanced Hunting and name it "Daily Patch Priority Queue". When everyone works from the same prioritised list, you eliminate conflicting priorities and wasted effort.

Step 7 ยท Hunt for Vulnerability Exploitation Evidence

Detection is the counterpart to prevention. While DVM tells you what could be exploited, hunting for exploitation evidence tells you what is being exploited. By querying endpoint detection events for blocked exploit attempts, you can confirm which CVEs attackers are actively targeting in your environment and escalate their remediation accordingly.

// WHAT: Detect active exploitation attempts blocked by Defender for Endpoint
// WHY: These events confirm that attackers are actively targeting your environment.
//      CVEs being exploited against YOUR devices should be patched immediately.
// TABLE: DeviceEvents - endpoint detection events from MDE sensor
// KEY ActionType values for exploit detection:
//   ExploitGuardNetworkProtectionBlocked - network exploit blocked by Network Protection
//   ExploitGuardASRViolationBlocked      - blocked by Attack Surface Reduction (ASR) rules
//     ASR rules protect against common attack vectors: Office macro execution,
//     credential theft from LSASS, ransomware delivery, etc.
// OUTPUT: Device name, blocked action type, target URL, and attempt count
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType in ("ExploitGuardNetworkProtectionBlocked", "ExploitGuardASRViolationBlocked")
| summarize Attempts = count() by DeviceName, ActionType, RemoteUrl
| order by Attempts desc
// ============================================================
// Correlate Exploit Blocks with Unpatched Vulnerabilities
// ============================================================
// WHAT: Cross-references devices that blocked exploit attempts
//       with their current vulnerability inventory to find
//       devices under active attack that still have unpatched CVEs.
// WHY:  A device blocking exploits today may be successfully
//       exploited tomorrow if a new attack vector is found.
//       These devices need immediate patching.
let exploitTargets = DeviceEvents
| where Timestamp > ago(7d)
| where ActionType in (
    "ExploitGuardNetworkProtectionBlocked",
    "ExploitGuardASRViolationBlocked")
| summarize
    BlockedAttempts = count(),
    AttackTypes     = make_set(ActionType, 3)
    by DeviceId, DeviceName;
let vulnerableDevices = DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel in ("Critical", "High")
| where IsExploitAvailable == true
| summarize
    OpenCVEs       = dcount(CveId),
    CriticalCVEs   = dcountif(CveId, VulnerabilitySeverityLevel == "Critical"),
    VulnSoftware   = make_set(SoftwareName, 3)
    by DeviceId;
exploitTargets
| join kind=inner vulnerableDevices on DeviceId
| extend Urgency = "๐Ÿšจ UNDER ACTIVE ATTACK + UNPATCHED"
| order by BlockedAttempts desc
| project Urgency, DeviceName, BlockedAttempts, AttackTypes,
          OpenCVEs, CriticalCVEs, VulnSoftware
💡 Pro Tip: Devices that appear in both the "exploit blocked" and "unpatched critical CVEs" lists should be escalated to P0 immediately. Today's blocked exploit may succeed tomorrow with a slightly different technique. Defence-in-depth means patching and detecting, not relying on detection alone.

Step 8 ยท Configure Automated Threat Alerts

Automated alerting closes the gap between intelligence discovery and remediation action. This step creates custom detection rules and a PowerShell-based TI-enriched dashboard that combines DVM vulnerability data with CISA KEV status and exploit prediction scores into a single prioritised view.

  1. Create custom detection rules for new critical exploitable CVEs appearing on your devices
  2. Set up email alerts for new threat analytics reports affecting your software inventory
  3. Configure SIEM integration for vulnerability-threat correlation events
# ============================================================
# TI-Enriched Vulnerability Dashboard Generator
# ============================================================
# WHAT: Pulls DVM vulnerability data, enriches with CISA KEV
#       status, and generates an HTML dashboard showing the
#       threat-informed priority queue.
# WHY:  Combines multiple data sources into a single actionable
#       view that can be emailed to leadership or displayed on
#       a SOC wall monitor.
# ============================================================

Connect-MgGraph -Scopes "SecurityEvents.Read.All"

# Step 1: Get CISA KEV list
$kevData = Invoke-RestMethod -Uri "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
$kevCVEs = $kevData.vulnerabilities | Select-Object -ExpandProperty cveID
Write-Host "Loaded $($kevCVEs.Count) CISA KEV entries" -ForegroundColor Cyan

# Step 2: Pull DVM vulnerability data
$vulns = Invoke-MgGraphRequest -Method GET `
    -Uri "https://graph.microsoft.com/beta/security/vulnerabilities/softwareVulnerabilities?`$top=5000" `
    -OutputType PSObject

# Step 3: Enrich with KEV status and calculate risk score
$enrichedVulns = $vulns.value |
    Group-Object -Property cveId |
    ForEach-Object {
        $cve = $_.Name
        $devices = $_.Group
        $severity = ($devices | Select-Object -First 1).vulnerabilitySeverityLevel
        $exploitable = ($devices | Where-Object { $_.isExploitAvailable }).Count -gt 0
        $internetFacing = ($devices | Where-Object { $_.isInternetFacing }).Count
        $isKEV = $cve -in $kevCVEs

        # Calculate composite risk score
        $score = 0
        if ($severity -eq 'Critical') { $score += 40 }
        if ($severity -eq 'High')     { $score += 20 }
        if ($exploitable)             { $score += 30 }
        if ($internetFacing -gt 0)    { $score += 20 }
        if ($isKEV)                   { $score += 50 }  # KEV = highest weight

        [PSCustomObject]@{
            CVE             = $cve
            Severity        = $severity
            AffectedDevices = $devices.Count
            InternetFacing  = $internetFacing
            ExploitAvail    = $exploitable
            CISA_KEV        = $isKEV
            RiskScore       = $score
            SLA             = switch {
                ($score -ge 90) { "24 hours" }
                ($score -ge 70) { "72 hours" }
                ($score -ge 50) { "7 days"   }
                default         { "30 days"  }
            }
        }
    } |
    Sort-Object RiskScore -Descending

# Step 4: Display top priorities
Write-Host "`n๐Ÿšจ TOP 20 THREAT-INFORMED PRIORITIES" -ForegroundColor Red
Write-Host ("โ”" * 80) -ForegroundColor Cyan
$enrichedVulns | Select-Object -First 20 |
    Format-Table CVE, Severity, RiskScore, SLA, AffectedDevices,
                 InternetFacing, ExploitAvail, CISA_KEV -AutoSize

# Step 5: Export full report
$reportPath = "C:\Reports\TI-Enriched-Vulns-$(Get-Date -Format 'yyyy-MM-dd').csv"
$enrichedVulns | Export-Csv -Path $reportPath -NoTypeInformation
Write-Host "โœ… Full report: $reportPath" -ForegroundColor Green
💡 Pro Tip: Schedule this script as a daily Azure Automation runbook. Email the HTML report to the patching team at 7 AM so they can start every day with a fresh, threat-informed priority list. Include a diff section showing what changed since yesterday - new CVEs added, KEV matches found, devices patched.

Step 9 ยท Generate Risk Reports

Risk reports should tell the story of your threat-informed vulnerability management programme: what the real-world threat landscape looks like, how your exposure maps to active campaigns, what you remediated, and what remains. Frame every data point in terms of business risk, not technical severity.

  1. Create monthly risk reports showing: total exposure, threat-informed priorities, remediation progress
  2. Include metrics: exploitable CVEs patched, exposure score reduction, exploit coverage
  3. Present risk in business terms: number of devices at risk from active campaigns
  4. Track remediation SLA compliance for threat-informed priority CVEs
// ============================================================
// Monthly Risk Report: Remediation SLA Compliance
// ============================================================
// WHAT: Tracks whether critical and high-severity exploitable
//       CVEs were remediated within their assigned SLA windows.
// WHY:  SLA compliance is the operational metric that proves
//       your threat-informed VM programme is working.
DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel in ("Critical", "High")
| where IsExploitAvailable == true
| summarize
    FirstSeen       = min(Timestamp),
    AffectedDevices = dcount(DeviceId)
    by CveId, VulnerabilitySeverityLevel
| extend ExposureDays = datetime_diff('day', now(), FirstSeen)
| extend SLA = case(
    VulnerabilitySeverityLevel == "Critical", 7,
    VulnerabilitySeverityLevel == "High", 30,
    90)
| extend SLAStatus = iff(ExposureDays > SLA,
    "๐Ÿ”ด SLA BREACHED", "๐ŸŸข Within SLA")
| summarize
    TotalCVEs       = count(),
    WithinSLA       = countif(ExposureDays <= SLA),
    SLABreached     = countif(ExposureDays > SLA)
    by VulnerabilitySeverityLevel
| extend SLACompliance = strcat(
    tostring(round(100.0 * WithinSLA / TotalCVEs, 1)), "%")
| project VulnerabilitySeverityLevel, TotalCVEs,
          WithinSLA, SLABreached, SLACompliance
💡 Pro Tip: Frame your report around three headlines: (1) "X devices are at risk from active campaigns" (business impact), (2) "We remediated Y% of threat-informed priorities within SLA" (operational performance), and (3) "Our exposure score moved from A to B" (trend direction). These three statements tell the complete story in 30 seconds.

Step 10 ยท Design Threat-Informed VM Program

A threat-informed vulnerability management programme is the culmination of all previous steps: it embeds threat intelligence into every prioritisation decision, uses automated tooling to surface urgent CVEs, tracks remediation against SLAs, and reports risk in business language. This final step establishes the operational cadence that makes it sustainable.

  • Daily: Monitor event timeline for new exploits and threat associations
  • Weekly: Re-prioritise remediation based on new intelligence
  • Monthly: Comprehensive risk report with trend analysis
  • Quarterly: Review program effectiveness and adjust scoring models
💡 Pro Tip: The ultimate maturity indicator for your VM programme is this: when a new zero-day is announced, how quickly can you answer three questions? (1) Are we affected? (2) How many devices? (3) Are they internet-facing? If you can answer all three in under 5 minutes using your dashboard, your programme is mature. If it takes hours of manual research, automate the workflow using the queries from this lab.

Summary

What You Accomplished

  • Integrated exploit predictions and active threat campaign data
  • Correlated vulnerabilities with MITRE ATT&CK techniques
  • Built threat-informed remediation priorities
  • Created risk analytics dashboards with KQL
  • Established a threat-informed vulnerability management program

Next Steps

  • Integrate DVM with Microsoft Sentinel for SOAR-driven patch management
  • Deploy External Attack Surface Management (EASM) for outside-in visibility
  • Connect threat intelligence feeds for enhanced vulnerability-threat correlation

๐Ÿ“š Documentation Resources

ResourceDescription
Exploit predictionHow DVM predicts likelihood of exploitation for each CVE
Threat analyticsTrack active threat campaigns and their targeted vulnerabilities
CISA KEV CatalogueAuthoritative list of CVEs actively exploited in the wild
Event timelineTrack vulnerability lifecycle events: disclosure, exploit, patch
MITRE ATT&CK FrameworkMap vulnerabilities to adversary techniques and tactics
DeviceTvmSoftwareVulnerabilitiesAdvanced Hunting schema for vulnerability-threat correlation
โ† Previous Lab All Labs โ†’