To list vulnerable software in Microsoft Defender, query the DeviceTvmSoftwareVulnerabilities table in advanced hunting, which holds the vulnerable software on each device with its CVE, severity and the security update that fixes it. The table comes from Microsoft Defender for Endpoint, so only onboarded devices appear. It needs Defender for Endpoint Plan 2 or Defender Vulnerability Management; Defender for Business doesn't include it.
| Method | Best fit |
|---|---|
| PowerShell | A CSV by device, program and CVE, up to 100,000 rows, from 1 advanced hunting query. |
| Admin centre | Working through programs and CVEs in the Defender portal, with the devices exposed. |
| Altivane | Recommended for recurring reviews, with every vulnerability on every device in a workbook. |
Before you start
Use an account that can run advanced hunting in the Microsoft Defender portal. The PowerShell example requests ThreatHunting., the only permission Microsoft lists for the hunting API; your organisation may require administrator consent.
Microsoft says a fix typically shows within 24 to 48 hours of the device reporting the new version, so a patch installed today can still show. Software without an official product code (CPE) isn't covered by vulnerability management. The examples read and export and change nothing.
Option 1
List vulnerable software with PowerShell
Install the module once, then connect, run the query through Microsoft Graph and export the rows.
# Install once, if the module is not already installed.
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'ThreatHunting.Read.All' -NoWelcome
try {
$columns = 'DeviceName', 'OSPlatform', 'SoftwareVendor', 'SoftwareName', 'SoftwareVersion',
'CveId', 'VulnerabilitySeverityLevel', 'RecommendedSecurityUpdate'
$query = "DeviceTvmSoftwareVulnerabilities | project $($columns -join ', ')" +
' | order by DeviceName asc, SoftwareName asc'
$body = @{ Query = $query } | ConvertTo-Json
$uri = 'https://graph.microsoft.com/v1.0/security/runHuntingQuery'
$request = @{ Method = 'POST'; Uri = $uri; Body = $body; ContentType = 'application/json' }
$response = Invoke-MgGraphRequest @request
$rows = @($response.results | ForEach-Object { [pscustomobject]$_ } | Select-Object $columns)
if ($rows.Count -eq 0) {
Write-Output 'Advanced hunting returned no vulnerable software.'
} else {
$rows | Export-Csv -Path './vulnerable-software.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($rows.Count) rows written to vulnerable-software.csv."
if ($rows.Count -ge 100000) { Write-Warning 'Stopped at 100,000 rows: narrow the query.' }
}
} finally {
Disconnect-MgGraph | Out-Null
}The file has 1 row for each device, program and CVE, so 1 old browser on 40 devices with 10 CVEs gives 400 rows. RecommendedSecurityUpdate names the update that fixes it, where the publisher has one. Microsoft returns at most 100,000 rows and 50 MB from 1 query, so on a large tenant the list can stop short; the script warns at 100,000 rows. To narrow it, add a where line to the query before project, by severity or device, such as | where VulnerabilitySeverityLevel == 'Critical' or | where DeviceName startswith 'lon-'.
Count vulnerable software across devices
Reconnect with Connect-MgGraph, then run a query that gives 1 row per program with how many devices and CVEs it has. The main export above disconnects when it finishes.
# Run while connected to Microsoft Graph with ThreatHunting.Read.All.
$query = 'DeviceTvmSoftwareVulnerabilities' +
' | summarize Devices = dcount(DeviceId), CVEs = dcount(CveId)' +
' by SoftwareVendor, SoftwareName | order by Devices desc'
$body = @{ Query = $query } | ConvertTo-Json
$uri = 'https://graph.microsoft.com/v1.0/security/runHuntingQuery'
$response = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $body -ContentType 'application/json'
$response.results | ForEach-Object { [pscustomobject]$_ } | Select-Object -First 20Option 2
Review vulnerable software in the Defender portal
- Sign in to the Microsoft Defender portal for the correct tenant.
- Go to Endpoints > Vulnerability management > Inventories and select the Software tab. In the newer layout it's under Exposure management > Vulnerability management > Inventories.
- Read Weaknesses and Exposed devices for each program, and filter by OS platform, weaknesses or tags such as end of support.
- Select a program and open its software page, then select Discovered vulnerabilities for its CVEs.
- For every CVE at once, open Weaknesses from the vulnerability management menu (Vulnerabilities in the newer layout) and export the list. Leave the pages without changing anything.
This suits working through the worst programs in Microsoft's own pages. The weaknesses export stops at 6,000 records and 64 KB, and the device view means opening each device, so for a full list by device, use PowerShell or Altivane.
Option 3 ยท Recommended for recurring reviews
Report on vulnerable software with Altivane
- Open Altivane and choose the tenant.
- Run the Vulnerable Software report. It reads every device's software, so it's slow on a large tenant.
- Open the tenant's Excel workbook and find the Vulnerable software table: every vulnerability on every device, the highest CVSS score first, with the software and version, the CVE, its severity and CVSS score, its exploitability, the update that fixes it and when it was first seen.
- For the fixes ranked by severity and the devices each would protect, run the Security Recommendations report.
The report needs a tenant signed in with a certificate and licensed for Defender Vulnerability Management.
Contact usCommon questions
Why does the query return no rows?
The table is filled by Defender for Endpoint. If the organisation hasn't deployed it, or no device is onboarded, Microsoft says queries on the table return nothing. Check the licence too: Defender for Business doesn't include vulnerability management.
Why does a program show as vulnerable after it was updated?
Microsoft says a fix typically shows within 24 to 48 hours of the device reporting the new version. The software inventory updates every 3 to 4 hours and can't be forced. Wait 2 days, then run the export again before you chase the device's owner.
How do I find devices on Windows versions that no longer get updates?
Software on an unsupported Windows build may never get a fix. To find those devices in Intune, see how to find unsupported Windows versions in Intune.
Microsoft references
Technical references checked on 6 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.
- Device
Tvm Software Vulnerabilities table - security: runHuntingQuery in Microsoft Graph
- Advanced hunting limits in the Microsoft Graph security API
- Software inventory in Defender Vulnerability Management
- Vulnerabilities in the Defender portal
- Compare Defender Vulnerability Management offerings
- Invoke-MgGraphRequest reference