Custom compliance policies in Intune let you check any device setting that is not covered by the built-in compliance options. You write a PowerShell detection script, define the rules to evaluate the output, and Intune marks devices compliant or non-compliant based on the result. This guide walks through building a complete custom compliance policy from script to Conditional Access enforcement.
How custom compliance works
The flow is straightforward:
- You write a PowerShell script that checks settings and outputs a JSON object
- You upload the script to Intune and define rules against its output values
- Intune runs the script on each device and evaluates the rules
- Devices that fail any rule are marked non-compliant
Write the detection script
The script must output a JSON object to stdout using return (not Write-Output). Each key becomes a setting you can create a rule against.
# Custom Compliance Detection Script
# Returns JSON with device settings for Intune to evaluate
$result = @{}
# Check 1: Minimum OS build
$result["OSBuild"] = [System.Environment]::OSVersion.Version.Build
# Check 2: BitLocker status on C:
$blStatus = Get-BitLockerVolume -MountPoint "C:" -ErrorAction SilentlyContinue
$result["BitLockerEnabled"] = ($blStatus.ProtectionStatus -eq "On")
# Check 3: Windows Defender real-time protection
$defenderStatus = Get-MpComputerStatus -ErrorAction SilentlyContinue
$result["DefenderRealTimeEnabled"] = ($defenderStatus.RealTimeProtectionEnabled -eq $true)
# Check 4: Screen lock timeout (in seconds from registry)
$lockTimeout = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "InactivityTimeoutSecs" -ErrorAction SilentlyContinue).InactivityTimeoutSecs
$result["ScreenLockTimeoutSecs"] = if ($lockTimeout) { [int]$lockTimeout } else { 0 }
return $result | ConvertTo-Json -CompressCreate the custom compliance policy
- Click + Add under Detection script
- Upload your .ps1 detection script
- Move to the Compliance settings tab
- Define rules for each setting your script returns
Define compliance rules
For each key your script returns, you can create a rule. The operator options depend on the data type:
Assign and monitor
Assign the policy to device or user groups as with any compliance policy. Monitor results under Devices > Compliance > select policy > Device status.
Devices that fail custom compliance rules show as non-compliant in the same view as built-in compliance failures, and feed into Conditional Access just the same.
More useful examples
Check if a specific application is installed
$result = @{}
$app = Get-CimInstance -ClassName Win32_Product | Where-Object { $_.Name -like "*CrowdStrike*" }
$result["CrowdStrikeInstalled"] = ($null -ne $app)
return $result | ConvertTo-Json -CompressCheck TPM version
$result = @{}
$tpm = Get-Tpm -ErrorAction SilentlyContinue
$result["TPMVersion"] = if ($tpm.TpmPresent) { "2.0" } else { "none" }
return $result | ConvertTo-Json -CompressFrequently Asked Questions
A custom compliance policy lets you write a PowerShell detection script that checks any setting on a device and returns a JSON result. Intune evaluates the JSON against rules you define and marks the device compliant or non-compliant based on the result. This extends built-in compliance checks with anything you can script.
The script must output a single JSON object where each key is a setting name and the value is the current value on the device. For example: {"DiskEncrypted": true, "OSVersion": "10.0.19045"}. Intune compares these values against the rules you define in the compliance policy.
Yes. Custom compliance policies feed into the overall device compliance state. If a device fails a custom compliance check, it is marked non-compliant and Conditional Access policies that require compliant devices will block access.
The detection script runs on the same schedule as compliance evaluation - by default every 8 hours, and immediately when the device checks in. You can trigger a manual compliance check from the Intune portal or by running: Start-Process "C:\Program Files\Microsoft Intune Management Extension\Microsoft.Management.Services.IntuneWindowsAgent.exe"