All scripts
Governance 616

Get-DefenderDeviceRiskReport

Pulls every device's risk score from Microsoft Defender for Endpoint via Graph Security API and flags anything above Medium, a fast weekly triage list before you open the full portal.

Get-DefenderDeviceRiskReport.ps1
<#
.SYNOPSIS
    Get-DefenderDeviceRiskReport.ps1 - Reports device risk scores from Microsoft Defender for Endpoint.

.DESCRIPTION
    Queries the Defender for Endpoint API directly for every onboarded machine's
    current risk score, health status and exposure level, and highlights anything
    at Medium risk or above. Requires an app registration with Machine.Read.All
    application permission on the WindowsDefenderATP API.

.AUTHOR
    Shehryar Hassan

.EXAMPLE
    .\Get-DefenderDeviceRiskReport.ps1 -TenantId "..." -ClientId "..." -ClientSecret (Read-Host -AsSecureString)
#>

param(
    [Parameter(Mandatory=$true)]
    [string]$TenantId,

    [Parameter(Mandatory=$true)]
    [string]$ClientId,

    [Parameter(Mandatory=$true)]
    [securestring]$ClientSecret,

    [Parameter(Mandatory=$false)]
    [string]$OutputPath = ".\DeviceRiskReport.csv"
)

Write-Host "=============================================" -ForegroundColor Cyan
Write-Host "  Defender for Endpoint Device Risk Report" -ForegroundColor Cyan
Write-Host "=============================================" -ForegroundColor Cyan

# Get an app-only token for the WindowsDefenderATP API (separate from Graph)
$plainSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ClientSecret))
$body = @{
    grant_type    = "client_credentials"
    client_id     = $ClientId
    client_secret = $plainSecret
    resource      = "https://api.securitycenter.microsoft.com"
}
$token = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$TenantId/oauth2/token" -Body $body
$headers = @{ Authorization = "Bearer $($token.access_token)" }

try {
    $machines = Invoke-RestMethod -Method Get -Uri "https://api.securitycenter.microsoft.com/api/machines" -Headers $headers
} catch {
    Write-Error "[ERROR] Failed to query Defender for Endpoint machines: $_"
    exit 1
}

$report = $machines.value | Select-Object computerDnsName, osPlatform, healthStatus, riskScore, exposureLevel, lastSeen

$report | Export-Csv -Path $OutputPath -NoTypeInformation

$atRisk = $report | Where-Object { $_.riskScore -in @("Medium", "High") }
Write-Host "[SUCCESS] $($report.Count) device(s) written to: $OutputPath" -ForegroundColor Green
if ($atRisk) {
    Write-Host "[WARNING] $($atRisk.Count) device(s) at Medium risk or above:" -ForegroundColor Red
    $atRisk | Format-Table computerDnsName, riskScore, exposureLevel -AutoSize
} else {
    Write-Host "[INFO] No devices currently above Low risk." -ForegroundColor Green
}

Read it before you run it, and test in a safe tenant first.