[{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/posts/","section":"Blog","summary":"","title":"Blog","type":"posts"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"A couple of weeks ago I wrote about confirming the escrow of BitLocker recovery keys in Microsoft Entra — driven by the urgency of the Secure Boot certificate changes. On the macOS side, there is no equivalent certificate crisis forcing our hand right now, but that does not make FileVault key escrow any less important.\nmacOS continues to grow as a platform in the enterprise. More and more organizations are offering Macs as a choice — or even a default — for their workforce, and with Apple Silicon delivering strong performance across developer, creative, and general productivity workloads, that trend is only accelerating. As your Mac fleet grows, so does the importance of managing it with the same rigour you apply to Windows.\nHaving your FileVault recovery keys safely stored in Entra is simply good operational hygiene. Let me walk you through why, how to report on it, and how to remediate devices that have fallen through the cracks.\nWhy You Want FileVault Keys Escrowed # There are several scenarios where having the recovery key readily available in your tenant saves you from a world of pain:\nUser incidents — Whether an employee leaves the organization and you need to recover data or repurpose their Mac, or a user simply forgets their macOS login password — the recovery key is your way back in. Without an escrowed key, a FileVault-encrypted disk becomes a brick.\nDevice recovery after hardware repair — After a logic board replacement or certain firmware updates, macOS may prompt for FileVault recovery. If the key was never escrowed, you\u0026rsquo;re looking at a full disk wipe.\nCompliance and audit readiness — Regulatory frameworks and internal policies often require proof that disk encryption keys are centrally managed. Having keys escrowed in Entra gives you that audit trail.\nIncident response — In a security incident, your SOC team may need to unlock and examine a device urgently. Waiting for a user who is unavailable (or compromised) is not an option when time matters.\nThe common thread here is simple: if the key is not escrowed, your options reduce to wiping the device and losing the data. That is never a good position to be in.\nThe Remediation Script # To address devices that have FileVault enabled but have never escrowed their recovery key to Intune, I have put together a script that can be deployed as a shell script through Intune.\nThe script performs four checks and actions:\nVerifies FileVault is enabled on the device Verifies the MDM escrow profile (FDERecoveryKeyEscrow) is present Downloads and installs Escrow Buddy if not already present Sets the GenerateNewKey flag to trigger key escrow at the next user login 📖 remediateFileVaultEscrow.zsh — GitHub\n📜 View remediation script #!/bin/zsh #set -x ############################################################################################ ## ## remediateFileVaultEscrow.zsh ## ## Remediates macOS devices where FileVault is enabled but the recovery key ## has never been escrowed to Intune. Uses Escrow Buddy (by Netflix/macadmins) ## to generate and escrow a new key at the next user login. ## ## https://github.com/macadmins/escrow-buddy ## ## Prerequisites: ## - FileVault must already be enabled on the device ## - The Intune FileVault configuration profile (with FDERecoveryKeyEscrow) ## must be assigned ## ## Designed to run as root via Microsoft Intune shell script deployment. ## ## What this script does: ## 1. Verifies FileVault is enabled ## 2. Verifies the MDM escrow profile is present ## 3. Downloads and installs Escrow Buddy if not already present ## 4. Sets GenerateNewKey flag to trigger key escrow at next login ## ## Logging: /Library/Logs/Intune/RemediateFileVaultEscrow.log ## ## Author: Simon Pauly Kofoed Mose ## Blog: https://paulycloud.com ## Version: 2.0 - Replaced fdesetup approach with Escrow Buddy ## 1.0 - Initial release ## ############################################################################################ ## Define variables appname=\u0026#34;RemediateFileVaultEscrow\u0026#34; logandmetadir=\u0026#34;/Library/Logs/Intune\u0026#34; logfile=\u0026#34;$logandmetadir/$appname.log\u0026#34; ## Escrow Buddy escrowBuddyPlugin=\u0026#34;/Library/Security/SecurityAgentPlugins/Escrow Buddy.bundle\u0026#34; escrowBuddyPkg=\u0026#34;https://github.com/macadmins/escrow-buddy/releases/download/v1.0.0/Escrow.Buddy-1.0.0.pkg\u0026#34; escrowBuddyPlist=\u0026#34;/Library/Preferences/com.netflix.Escrow-Buddy.plist\u0026#34; ## Create log directory if needed if [ ! -d \u0026#34;$logandmetadir\u0026#34; ]; then mkdir -p \u0026#34;$logandmetadir\u0026#34; fi ############################################################################################ ## Functions ############################################################################################ log () { local msg=\u0026#34;$(date) | $*\u0026#34; echo \u0026#34;$msg\u0026#34; echo \u0026#34;$msg\u0026#34; \u0026gt;\u0026gt; \u0026#34;$logfile\u0026#34; } downloadFile () { local url=\u0026#34;$1\u0026#34; local dest=\u0026#34;$2\u0026#34; local maxAttempts=3 local attempt=1 while [ $attempt -le $maxAttempts ]; do log \u0026#34;Downloading [$url] (attempt $attempt of $maxAttempts)\u0026#34; if curl -f -s -L --connect-timeout 30 -o \u0026#34;$dest\u0026#34; \u0026#34;$url\u0026#34;; then log \u0026#34;Download successful\u0026#34; return 0 fi log \u0026#34;Download attempt $attempt of $maxAttempts failed\u0026#34; attempt=$((attempt + 1)) [ $attempt -le $maxAttempts ] \u0026amp;\u0026amp; sleep 10 done log \u0026#34;Download failed after $maxAttempts attempts\u0026#34; return 1 } ############################################################################################ ## Begin Script Body ############################################################################################ log \u0026#34;Starting $appname\u0026#34; ## ## 1. Check if FileVault is enabled ## fvStatus=$(fdesetup status) if ! echo \u0026#34;$fvStatus\u0026#34; | grep -q \u0026#34;FileVault is On\u0026#34;; then log \u0026#34;FileVault is not enabled. Nothing to remediate.\u0026#34; log \u0026#34;Status: $fvStatus\u0026#34; exit 0 fi log \u0026#34;FileVault is enabled\u0026#34; ## ## 2. Check if the MDM escrow profile is present ## if ! profiles show -all 2\u0026gt;/dev/null | grep -q \u0026#34;com.apple.security.FDERecoveryKeyEscrow\u0026#34;; then log \u0026#34;No FDERecoveryKeyEscrow profile found. Assign the Intune FileVault policy first.\u0026#34; exit 1 fi log \u0026#34;MDM escrow profile is present\u0026#34; ## ## 3. Install Escrow Buddy if not already present ## if [ -d \u0026#34;$escrowBuddyPlugin\u0026#34; ]; then log \u0026#34;Escrow Buddy already installed at [$escrowBuddyPlugin]\u0026#34; else log \u0026#34;Escrow Buddy not found, downloading and installing...\u0026#34; tmpPkg=$(mktemp /tmp/escrow_buddy_XXXXX.pkg) if ! downloadFile \u0026#34;$escrowBuddyPkg\u0026#34; \u0026#34;$tmpPkg\u0026#34;; then log \u0026#34;Failed to download Escrow Buddy. Exiting.\u0026#34; rm -f \u0026#34;$tmpPkg\u0026#34; exit 1 fi if installer -pkg \u0026#34;$tmpPkg\u0026#34; -target /; then log \u0026#34;Escrow Buddy installed successfully\u0026#34; else log \u0026#34;Failed to install Escrow Buddy. Exiting.\u0026#34; rm -f \u0026#34;$tmpPkg\u0026#34; exit 1 fi rm -f \u0026#34;$tmpPkg\u0026#34; fi ## ## 4. Set GenerateNewKey flag ## ## At the next user login, Escrow Buddy intercepts the login authorization ## and triggers a new personal recovery key generation + escrow ## log \u0026#34;Setting GenerateNewKey flag...\u0026#34; defaults write \u0026#34;$escrowBuddyPlist\u0026#34; GenerateNewKey -bool true if defaults read \u0026#34;$escrowBuddyPlist\u0026#34; GenerateNewKey 2\u0026gt;/dev/null | grep -q \u0026#34;1\u0026#34;; then log \u0026#34;GenerateNewKey flag set successfully\u0026#34; log \u0026#34;A new recovery key will be generated and escrowed at the next user login\u0026#34; else log \u0026#34;Failed to set GenerateNewKey flag\u0026#34; exit 1 fi log \u0026#34;$appname completed\u0026#34; Escrow Buddy — Solving the fdesetup Problem # You might wonder: why not just use Apple\u0026rsquo;s built-in fdesetup changerecovery command to rotate the key and escrow it? The answer is that fdesetup requires the user\u0026rsquo;s login password to be provided interactively or passed as input. In an MDM-driven, unattended deployment context, you simply do not have the user\u0026rsquo;s password available.\nThis is the problem that the team at Netflix set out to solve when they developed Escrow Buddy. It is now maintained under the macadmins GitHub organization and has become the community-standard approach for FileVault key escrow remediation.\nHow Escrow Buddy Works # Escrow Buddy installs as a Security Agent plugin (/Library/Security/SecurityAgentPlugins/Escrow Buddy.bundle). It hooks into the macOS login authorization process — the same mechanism that powers the login window itself.\nThe flow is straightforward:\nThe remediation script sets the GenerateNewKey flag in Escrow Buddy\u0026rsquo;s preferences At the next user login, Escrow Buddy captures the user\u0026rsquo;s credentials as they authenticate (the same way macOS itself does) It uses those credentials to call fdesetup changerecovery -personal behind the scenes The newly generated personal recovery key is then escrowed to the MDM server (Intune) via the FDERecoveryKeyEscrow profile payload The result: a new recovery key is generated and escrowed to Entra without any user interaction beyond their normal login. No prompts, no popups, no helpdesk tickets.\n📖 Escrow Buddy — GitHub (macadmins)\nKeeping Your Tenant in Good Shape # Whether you are managing Windows, macOS, or both — disk encryption key escrow is one of those things that should never be left to chance. It is easy to assume everything is working because the policies are deployed, but configuration drift, re-enrollments, and edge cases mean that some devices will inevitably slip through.\nMake it a regular practice to:\nReport on escrow status for both BitLocker and FileVault across your fleet Remediate gaps proactively rather than discovering them during an incident Validate after changes — any time you modify encryption policies, profiles, or enrollment flows, verify that keys are still being escrowed correctly If you haven\u0026rsquo;t already, take a look at my previous post on confirming BitLocker recovery key escrow for the Windows side of the house. Together, these two approaches give you full visibility and control over disk encryption recovery across your entire multi-platform fleet.\nStay on top of it — future you will be grateful.\n","date":"18 May 2026","externalUrl":null,"permalink":"/posts/confirm-escrow-of-filevault-recovery-keys/","section":"Blog","summary":"A couple of weeks ago I wrote about confirming the escrow of BitLocker recovery keys in Microsoft Entra — driven by the urgency of the Secure Boot certificate changes. On the macOS side, there is no equivalent certificate crisis forcing our hand right now, but that does not make FileVault key escrow any less important.\nmacOS continues to grow as a platform in the enterprise. More and more organizations are offering Macs as a choice — or even a default — for their workforce, and with Apple Silicon delivering strong performance across developer, creative, and general productivity workloads, that trend is only accelerating. As your Mac fleet grows, so does the importance of managing it with the same rigour you apply to Windows.\n","title":"Confirm Escrow of FileVault Recovery Keys in Microsoft Entra","type":"posts"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/escrow-buddy/","section":"Tags","summary":"","title":"Escrow Buddy","type":"tags"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/filevault/","section":"Tags","summary":"","title":"FileVault","type":"tags"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/intune/","section":"Tags","summary":"","title":"Intune","type":"tags"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/categories/intune-tips/","section":"Categories","summary":"","title":"Intune Tips","type":"categories"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/macos/","section":"Tags","summary":"","title":"MacOS","type":"tags"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/microsoft-entra-id/","section":"Tags","summary":"","title":"Microsoft Entra ID","type":"tags"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/","section":"PaulyCloud — Intune \u0026 Endpoint Management Blog","summary":"","title":"PaulyCloud — Intune \u0026 Endpoint Management Blog","type":"page"},{"content":"","date":"18 May 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"4 May 2026","externalUrl":null,"permalink":"/tags/certutil/","section":"Tags","summary":"","title":"Certutil","type":"tags"},{"content":"Sometimes users need to have their Windows Hello for Business container reset. This can happen for a myriad of reasons:\nBiometrics stopped working \u0026ldquo;Something went wrong\u0026rdquo; errors during sign-in that won\u0026rsquo;t resolve Trust relationship between the credential and Microsoft Entra ID broke User suspects their PIN was observed or compromised Device was lost briefly and recovered — user wants to re-key For this support request, you can easily push a small script using Intune\u0026rsquo;s on-demand remediation feature (preview). All it does is use certutil to delete the Windows Hello container and return the exit code.\nIf the container has been successfully deleted, the user will be prompted to set up Windows Hello for Business after the next sign-out and sign-in, or after a restart.\n⚠️ Warning: The certutil -DeleteHelloContainer command removes all credentials stored in the Windows Hello container, including any WebAuthn and FIDO2 passkeys. Users will need to re-register any passkeys after re-enrolling.\n📖 certutil -DeleteHelloContainer — Microsoft Learn\nThe Script # 📖 Detect-DeleteHelloContainer.ps1 — GitHub\n📜 View full script \u0026lt;# .SYNOPSIS Deletes the Windows Hello container for the current user. .DESCRIPTION Runs certutil -deleteHelloContainer to remove the Windows Hello for Business container. Must be run in the logged-on user\u0026#39;s context. Exit codes: - 0: Windows Hello container deleted successfully - 1: Failed to delete Windows Hello container .NOTES Author: Simon Pauly Kofoed Mose Blog: https://paulycloud.com Version: 1.0 - Initial release #\u0026gt; $result = certutil -deleteHelloContainer 2\u0026gt;\u0026amp;1 if ($LASTEXITCODE -eq 0) { Write-Host \u0026#34;COMPLIANT | Hello Container: Deleted | User: $env:USERNAME\u0026#34; exit 0 } else { Write-Host \u0026#34;NON-COMPLIANT | Hello Container: Failed to delete | User: $env:USERNAME | Exit Code: $LASTEXITCODE\u0026#34; exit 1 } How to Deploy # This uses the on-demand remediation feature (preview) in Intune. Upload the script as a detection script in a script package — no remediation script is needed, since the detection script itself performs the action.\nNavigate to Devices \u0026gt; Manage devices \u0026gt; Scripts and remediations Create a new script package Upload the script above as the detection script Configure it to: Run this script using the logged-on credentials — Yes Run script in 64-bit PowerShell — Yes Do not assign the script package to any group To initiate the reset: navigate to the target device and select Run remediation (preview) Important Notes # The script must run as the local logged-in user — if deployed as SYSTEM, it will fail silently and report false results The user must sign out and sign back in (or restart) after the container is deleted to be prompted for re-enrollment The script does not alert the user or force a reboot of the device — communicate this to the user separately All credentials in the Hello container are removed, including FIDO2/WebAuthn passkeys ","date":"4 May 2026","externalUrl":null,"permalink":"/posts/intune-tip-reset-windows-hello-container/","section":"Blog","summary":"Sometimes users need to have their Windows Hello for Business container reset. This can happen for a myriad of reasons:\nBiometrics stopped working “Something went wrong” errors during sign-in that won’t resolve Trust relationship between the credential and Microsoft Entra ID broke User suspects their PIN was observed or compromised Device was lost briefly and recovered — user wants to re-key For this support request, you can easily push a small script using Intune’s on-demand remediation feature (preview). All it does is use certutil to delete the Windows Hello container and return the exit code.\n","title":"IntuneTip: Reset Windows Hello for Business Using On-Demand Remediation","type":"posts"},{"content":"","date":"4 May 2026","externalUrl":null,"permalink":"/tags/powershell/","section":"Tags","summary":"","title":"PowerShell","type":"tags"},{"content":"","date":"4 May 2026","externalUrl":null,"permalink":"/tags/remediations/","section":"Tags","summary":"","title":"Remediations","type":"tags"},{"content":"","date":"4 May 2026","externalUrl":null,"permalink":"/tags/windows-hello-for-business/","section":"Tags","summary":"","title":"Windows Hello for Business","type":"tags"},{"content":"","date":"27 April 2026","externalUrl":null,"permalink":"/tags/bitlocker/","section":"Tags","summary":"","title":"BitLocker","type":"tags"},{"content":"","date":"27 April 2026","externalUrl":null,"permalink":"/tags/graph-api/","section":"Tags","summary":"","title":"Graph API","type":"tags"},{"content":"","date":"27 April 2026","externalUrl":null,"permalink":"/tags/secure-boot/","section":"Tags","summary":"","title":"Secure Boot","type":"tags"},{"content":"With the change of the Secure Boot certificates coming in fast and furious as summer approaches, it is paramount to ensure that your estate is ready to deploy the changes swiftly and securely.\nThe change and deployment has been documented thoroughly by several great community articles and contributions in recent months, along with the expansion of Microsoft\u0026rsquo;s own documentation on the subject.\nI will not delve further into that here other than to provide links for further reading, but if you\u0026rsquo;re looking at a deployment guide, I would highly suggest taking a look at Mindcore\u0026rsquo;s blog linked below:\n📖 Windows Secure Boot certificate expiration and CA updates — Microsoft Support\n📖 Windows Secure Boot Certificate Expiration 2026 — Mindcore Blog\nI will however touch upon a very specific part of your preparations towards this deployment to make sure it is smooth — one that has only become more important as of recently with the April update KB5083769 (OS Builds 26200.8246 and 26100.8246).\nIn the known issues of this update, Microsoft notes that devices deployed with an unrecommended BitLocker Group Policy configuration might be required to enter their BitLocker recovery key. The same update also addresses an issue where devices might enter BitLocker Recovery after the Secure Boot updates themselves.\nThis makes the confirmation of escrowed BitLocker recovery keys in Microsoft Entra absolutely paramount — if a device is prompted for its recovery key and that key was never backed up, you are looking at data loss or a very unpleasant recovery process.\nThe other week I sat down with a customer and built a script to identify which devices — those with both an Intune object and an Entra object — had escrowed BitLocker keys, and this is the result.\nThe Reporting Script # The script queries Microsoft Graph for BitLocker recovery keys stored in Microsoft Entra ID, cross-references them with Intune-managed and Entra-registered Windows devices, and produces a CSV report showing which devices have escrowed keys and which have not.\n⚠️ This script uses the Microsoft Graph beta endpoint. While functional, beta APIs may change without notice. The v1.0 endpoint also supports the BitLocker recovery key API if you prefer stability.\nRequired Graph API permissions:\nDevice.Read.All BitLockerKey.ReadBasic.All DeviceManagementManagedDevices.Read.All Windows 365 Cloud PC devices are automatically excluded from the report.\n📖 Get-BitLockerEntraEscrowStatus.ps1 — GitHub\n📜 View full reporting script \u0026lt;# .SYNOPSIS Reports whether BitLocker recovery keys are escrowed to Entra ID for Windows devices. .DESCRIPTION Queries Microsoft Graph for BitLocker recovery keys stored in Entra ID (Azure AD). This report does NOT include keys escrowed to on-premises Active Directory. Uses Microsoft.Graph.Authentication and native Invoke-MgGraphRequest calls. Windows 365 Cloud PC devices are excluded. Required Graph API permissions: - Device.Read.All - BitLockerKey.ReadBasic.All - DeviceManagementManagedDevices.Read.All .NOTES Run once to install the module: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Force Author: Simon Pauly Kofoed Mose Blog: https://paulycloud.com Version: 1.1 - Clarified Entra-only scope; renamed script 1.0 - Initial release #\u0026gt; # ── Variables ───────────────────────────────────────────────────────────────── $baseUri = \u0026#34;https://graph.microsoft.com/beta\u0026#34; $scopes = @( \u0026#34;Device.Read.All\u0026#34;, \u0026#34;BitLockerKey.ReadBasic.All\u0026#34;, \u0026#34;DeviceManagementManagedDevices.Read.All\u0026#34; ) # ── Functions ───────────────────────────────────────────────────────────────── function Initialize-MgGraphModule { if (-not (Get-Module -ListAvailable -Name \u0026#34;Microsoft.Graph.Authentication\u0026#34;)) { Write-Host \u0026#34;Installing Microsoft.Graph.Authentication...\u0026#34; -ForegroundColor Yellow Install-Module \u0026#34;Microsoft.Graph.Authentication\u0026#34; -Scope CurrentUser -Force } Import-Module \u0026#34;Microsoft.Graph.Authentication\u0026#34; -ErrorAction Stop Write-Host \u0026#34;Microsoft.Graph.Authentication module loaded.\u0026#34; -ForegroundColor Green } function Invoke-MgGraphRequestAll { param([string]$Uri) $results = [System.Collections.Generic.List[object]]::new() $nextUri = $Uri do { $response = Invoke-MgGraphRequest -Method GET -Uri $nextUri -OutputType PSObject if ($response.value) { $results.AddRange($response.value) } $nextUri = $response.\u0026#39;@odata.nextLink\u0026#39; } while ($nextUri) return $results } function Connect-Graph { Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null Connect-MgGraph -Scopes $scopes -ContextScope Process -NoWelcome Write-Host \u0026#34;Connected to Microsoft Graph.\u0026#34; -ForegroundColor Green } function Get-WindowsDevices { Write-Host \u0026#34;Fetching Windows devices from Entra...\u0026#34; -ForegroundColor Cyan $script:devices = Invoke-MgGraphRequestAll -Uri \u0026#34;$baseUri/devices?`$select=id,displayName,deviceId,operatingSystem,approximateLastSignInDateTime\u0026#34; | Where-Object { $_.operatingSystem -eq \u0026#34;Windows\u0026#34; } Write-Host \u0026#34; Found $($script:devices.Count) Windows device(s).\u0026#34; -ForegroundColor Cyan } function Get-BitLockerKeys { Write-Host \u0026#34;Fetching BitLocker recovery keys...\u0026#34; -ForegroundColor Cyan $script:bitlockerMap = @{} Invoke-MgGraphRequestAll -Uri \u0026#34;$baseUri/informationProtection/bitlocker/recoveryKeys\u0026#34; | ForEach-Object { $id = $_.deviceId $created = $_.createdDateTime if (-not $script:bitlockerMap.ContainsKey($id) -or $created -gt $script:bitlockerMap[$id]) { $script:bitlockerMap[$id] = $created } } Write-Host \u0026#34; Found keys for $($script:bitlockerMap.Count) device(s).\u0026#34; -ForegroundColor Cyan } function Get-IntuneDeviceInfo { Write-Host \u0026#34;Fetching Intune managed device info...\u0026#34; -ForegroundColor Cyan $script:intuneMap = @{} $script:cloudPcIds = @{} Invoke-MgGraphRequestAll -Uri \u0026#34;$baseUri/deviceManagement/managedDevices?`$select=id,azureADDeviceId,operatingSystem,lastSyncDateTime,model\u0026amp;`$filter=operatingSystem eq \u0026#39;Windows\u0026#39;\u0026#34; | ForEach-Object { $script:intuneMap[$_.azureADDeviceId] = @{ Id = $_.id; LastSync = $_.lastSyncDateTime; Model = $_.model } if ($_.model -and $_.model -match \u0026#34;Cloud PC\u0026#34;) { $script:cloudPcIds[$_.azureADDeviceId] = $true } } Write-Host \u0026#34; Found $($script:intuneMap.Count) Intune device(s), $($script:cloudPcIds.Count) Cloud PC(s) excluded.\u0026#34; -ForegroundColor Cyan } function Build-Report { Write-Host \u0026#34;Analyzing...\u0026#34; -ForegroundColor Yellow $script:report = foreach ($device in $script:devices) { $aadId = $device.deviceId # Skip Windows 365 Cloud PCs if ($script:cloudPcIds.ContainsKey($aadId)) { continue } # Match against both hardware deviceId and directory object id $escrowed = $script:bitlockerMap.ContainsKey($aadId) -or $script:bitlockerMap.ContainsKey($device.id) $keyCreated = if ($script:bitlockerMap.ContainsKey($aadId)) { $script:bitlockerMap[$aadId] } else { $script:bitlockerMap[$device.id] } [PSCustomObject]@{ DeviceName = $device.displayName DeviceId = $aadId IntuneDeviceId = $script:intuneMap[$aadId]?.Id Model = $script:intuneMap[$aadId]?.Model EscrowStatus = if ($escrowed) { \u0026#34;YES\u0026#34; } else { \u0026#34;NO\u0026#34; } KeyCreated = $keyCreated LastIntuneSync = $script:intuneMap[$aadId]?.LastSync LastEntraActivity = $device.approximateLastSignInDateTime } } } function Show-Summary { $withKey = ($script:report | Where-Object { $_.EscrowStatus -eq \u0026#34;YES\u0026#34; }).Count $withoutKey = ($script:report | Where-Object { $_.EscrowStatus -eq \u0026#34;NO\u0026#34; }).Count Write-Host \u0026#34;---------------------------------\u0026#34; -ForegroundColor Gray Write-Host \u0026#34;Devices with escrowed key : $withKey\u0026#34; -ForegroundColor Green Write-Host \u0026#34;Devices without escrowed key: $withoutKey\u0026#34; -ForegroundColor Red Write-Host \u0026#34;---------------------------------\u0026#34; -ForegroundColor Gray } function Export-Report { $reportsDir = Join-Path $PSScriptRoot \u0026#34;reports\u0026#34; if (-not (Test-Path $reportsDir)) { New-Item -ItemType Directory -Path $reportsDir | Out-Null } $tenantId = (Invoke-MgGraphRequest -Method GET -Uri \u0026#34;$baseUri/organization?`$select=id\u0026#34; -OutputType PSObject).value[0].id $date = Get-Date -Format \u0026#34;yyyy-MM-dd_HHmm\u0026#34; $baseName = \u0026#34;BitLockerEntraEscrow_${tenantId}_${date}\u0026#34; $csvPath = Join-Path $reportsDir \u0026#34;$baseName.csv\u0026#34; $script:report | Export-Csv $csvPath -NoTypeInformation -Encoding UTF8 Write-Host \u0026#34;CSV saved: $csvPath\u0026#34; -ForegroundColor Cyan return $reportsDir } # ── Execution ───────────────────────────────────────────────────────────────── $reportsDir = Join-Path $PSScriptRoot \u0026#34;reports\u0026#34; if (-not (Test-Path $reportsDir)) { New-Item -ItemType Directory -Path $reportsDir | Out-Null } $transcriptPath = Join-Path $reportsDir \u0026#34;BitLockerEntraEscrow_$(Get-Date -Format \u0026#39;yyyy-MM-dd_HHmm\u0026#39;).log\u0026#34; Start-Transcript -Path $transcriptPath -Force try { Initialize-MgGraphModule Connect-Graph Get-WindowsDevices Get-BitLockerKeys Get-IntuneDeviceInfo Build-Report Show-Summary Export-Report } finally { Disconnect-MgGraph -ErrorAction SilentlyContinue Stop-Transcript } Remediating Devices Without Escrowed Keys # If the report identifies devices that show NO for their escrow status, you can trigger a BitLocker key backup to Microsoft Entra ID remotely.\nDetection Script # Deploy this as an Intune Remediation detection script. It checks whether the device has at least one BitLocker recovery key protector backed up to Microsoft Entra ID:\n📖 Detect-BitLockerEscrow.ps1 — GitHub\n📜 View detection script # Detection: Check if BitLocker recovery key is escrowed to Entra ID try { $bitlockerVolume = Get-BitLockerVolume -MountPoint \u0026#34;C:\u0026#34; -ErrorAction Stop $recoveryProtector = $bitlockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq \u0026#34;RecoveryPassword\u0026#34; } if ($recoveryProtector) { # Check if the key has been backed up by looking for the recovery password $keyProtectorId = $recoveryProtector[0].KeyProtectorId if ($keyProtectorId) { Write-Output \u0026#34;BitLocker recovery key protector found: $keyProtectorId\u0026#34; exit 0 # Compliant — key exists } } Write-Output \u0026#34;No BitLocker recovery key protector found.\u0026#34; exit 1 # Non-compliant — needs remediation } catch { Write-Output \u0026#34;BitLocker is not enabled on C: drive. Error: $_\u0026#34; exit 1 # Non-compliant } Remediation Script # This script forces a backup of the BitLocker recovery key to Microsoft Entra ID:\n📖 Remediate-BitLockerEscrow.ps1 — GitHub\n📜 View remediation script # Remediation: Backup BitLocker recovery key to Entra ID try { $bitlockerVolume = Get-BitLockerVolume -MountPoint \u0026#34;C:\u0026#34; -ErrorAction Stop $recoveryProtector = $bitlockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq \u0026#34;RecoveryPassword\u0026#34; } if (-not $recoveryProtector) { # Add a recovery password protector if none exists Add-BitLockerKeyProtector -MountPoint \u0026#34;C:\u0026#34; -RecoveryPasswordProtector $bitlockerVolume = Get-BitLockerVolume -MountPoint \u0026#34;C:\u0026#34; $recoveryProtector = $bitlockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq \u0026#34;RecoveryPassword\u0026#34; } } # Backup the recovery key to Entra ID $keyProtectorId = $recoveryProtector[0].KeyProtectorId BackupToAAD-BitLockerKeyProtector -MountPoint \u0026#34;C:\u0026#34; -KeyProtectorId $keyProtectorId Write-Output \u0026#34;BitLocker recovery key backed up to Entra ID successfully.\u0026#34; exit 0 } catch { Write-Output \u0026#34;Failed to backup BitLocker key: $_\u0026#34; exit 1 } Conclusion # Before rolling out the Secure Boot certificate updates, take the time to confirm that your BitLocker recovery keys are safely escrowed in Microsoft Entra ID. The reporting script gives you full visibility across your estate, and the detection/remediation pair lets you close the gap automatically through Intune.\nIf you have questions or improvements, feel free to reach out!\n","date":"27 April 2026","externalUrl":null,"permalink":"/posts/confirm-escrow-of-bitlocker-recovery-keys/","section":"Blog","summary":"With the change of the Secure Boot certificates coming in fast and furious as summer approaches, it is paramount to ensure that your estate is ready to deploy the changes swiftly and securely.\nThe change and deployment has been documented thoroughly by several great community articles and contributions in recent months, along with the expansion of Microsoft’s own documentation on the subject.\nI will not delve further into that here other than to provide links for further reading, but if you’re looking at a deployment guide, I would highly suggest taking a look at Mindcore’s blog linked below:\n","title":"Secure Boot Certificates – Confirm Escrow of BitLocker Recovery Keys in Microsoft Entra","type":"posts"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/android/","section":"Tags","summary":"","title":"Android","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/app-protection-policy/","section":"Tags","summary":"","title":"App Protection Policy","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/categories/authentication/","section":"Categories","summary":"","title":"Authentication","type":"categories"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/byod/","section":"Tags","summary":"","title":"BYOD","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/conditional-access/","section":"Tags","summary":"","title":"Conditional Access","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/entra-id/","section":"Tags","summary":"","title":"Entra ID","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/ios/","section":"Tags","summary":"","title":"IOS","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/mam/","section":"Tags","summary":"","title":"MAM","type":"tags"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/microsoft-authenticator/","section":"Tags","summary":"","title":"Microsoft Authenticator","type":"tags"},{"content":"It is essential for some organizations to support BYOD for the iOS and Android platforms.\nThis is most easily done while protecting data by utilizing Mobile Application Management (MAM), App Protection Policies (APP), and Conditional Access policies to enforce it.\nAlong with this, we are all in the eternal search for features that provide more security and a better user experience. Such unicorn features are few and far between, as more security usually means impacting the end-user experience in some way.\nBut one such feature is the ability to use passkeys in the Microsoft Authenticator app on iOS and Android devices — a device-bound passkey that greatly enhances security, makes the login experience smoother, and reduces the need for passwords.\nBut there is an issue.\nThe Registration Flow # The current registration flow for the Passkey is as follows:\nOpen the Authenticator app and set up your account Create a passkey Authenticate towards Microsoft Entra ID Start using your passkey 🎉 📖 Register passkeys in Authenticator on Android or iOS devices\nBut the authentication requires a login from the Authenticator — an app that doesn\u0026rsquo;t support App Protection Policies, as it brokers the app-based Conditional Access policies on both iOS and Android.\n📖 Use app-based Conditional Access policies with Intune\nThis has the unfortunate result of blocking the device from registering the passkey.\nThe Obvious Solution # The obvious solution to this would be to exclude the Microsoft Authenticator app from the Conditional Access policy on iOS and Android devices, but\u0026hellip;\nFirst-party apps cannot be individually excluded when targeting \u0026ldquo;All resources\u0026rdquo; (formerly \u0026ldquo;All cloud apps\u0026rdquo;) in a Conditional Access policy.\nIs There a Workaround? # Is there a way to exclude the application anyway?\nYes, there is. Microsoft documents a few workarounds:\nFilter for applications — Use application filters to exclude the Authenticator app from the Conditional Access policy. MDM + compliant device — Enroll the device and require a compliant device grant instead. But that makes the whole point of BYOD void. Temporary exemption — Temporarily exempt users from the policy while they register their passkey. 📖 Users who can\u0026rsquo;t register passkeys because of CA grant controls\nConclusion # Let\u0026rsquo;s hope that Microsoft continues to improve the experience around the Authenticator app and Conditional Access.\nIn the meantime, if you want to use BYOD devices with passkeys for a phishing-resistant MFA option, the choice is either to:\nOption A: Use application filters to exclude the Microsoft Authenticator app from your Conditional Access policy.\nOption B: Create a CA policy that includes the client apps you want to protect, which automatically excludes the Microsoft Authenticator app.\n⚠️ This is not a great solution, as it will prevent blocking all apps not specifically assigned an APP or previously approved and excluded by IT.\nOption C: Simply not use passkeys for BYOD on iOS or Android\u0026hellip;\nIf you have stumbled upon a different solution, please let me know! 🙂\nIf I myself stumble upon a solution or something changes that allows for the exclusion of the Microsoft Authenticator app and allows the enforcement of an APP on all client apps on iOS and Android, I will make sure to update this article.\nUpdate 27 May 2025: Have a look at this article by Microsoft, linked in the comments of my original post by Rojan Koc: Users who can\u0026rsquo;t register passkeys because of Conditional Access grant controls\n","date":"20 May 2025","externalUrl":null,"permalink":"/posts/passkey-ios-android-registration-issue/","section":"Blog","summary":"It is essential for some organizations to support BYOD for the iOS and Android platforms.\nThis is most easily done while protecting data by utilizing Mobile Application Management (MAM), App Protection Policies (APP), and Conditional Access policies to enforce it.\nAlong with this, we are all in the eternal search for features that provide more security and a better user experience. Such unicorn features are few and far between, as more security usually means impacting the end-user experience in some way.\n","title":"Passkey (iOS/Android) Registration Issue","type":"posts"},{"content":"","date":"20 May 2025","externalUrl":null,"permalink":"/tags/passkeys/","section":"Tags","summary":"","title":"Passkeys","type":"tags"},{"content":" Welcome to PaulyCloud # PaulyCloud is a blog dedicated to Microsoft Intune and endpoint management. Here you\u0026rsquo;ll find practical guides, deep dives, and real-world tips for managing devices at scale in the modern workplace.\nWhat You\u0026rsquo;ll Find Here # Configuration Profiles — Settings catalog, templates, and custom OMA-URI to manage endpoints the right way Scripting \u0026amp; Automation — PowerShell scripts, remediation scripts, and Graph API to take the manual work out of endpoint management Windows Autopilot \u0026amp; Device Preparation — Zero-touch deployment, provisioning profiles, and modern device onboarding at scale Security Baselines — Hardening endpoints with Microsoft\u0026rsquo;s recommended settings and beyond Conditional Access — Integrating Intune with Entra ID to enforce the right access controls at the right time Device Compliance — Configuring and troubleshooting compliance policies that feed into your security posture App Deployment — Win32 apps, LOB apps, Microsoft Store apps, and everything in between Troubleshooting — Diagnosing and resolving the Intune issues you\u0026rsquo;ll inevitably run into Connect # Feel free to reach out or follow along on LinkedIn and GitHub.\n","externalUrl":null,"permalink":"/about/","section":"PaulyCloud — Intune \u0026 Endpoint Management Blog","summary":"Welcome to PaulyCloud # PaulyCloud is a blog dedicated to Microsoft Intune and endpoint management. Here you’ll find practical guides, deep dives, and real-world tips for managing devices at scale in the modern workplace.\nWhat You’ll Find Here # Configuration Profiles — Settings catalog, templates, and custom OMA-URI to manage endpoints the right way Scripting \u0026 Automation — PowerShell scripts, remediation scripts, and Graph API to take the manual work out of endpoint management Windows Autopilot \u0026 Device Preparation — Zero-touch deployment, provisioning profiles, and modern device onboarding at scale Security Baselines — Hardening endpoints with Microsoft’s recommended settings and beyond Conditional Access — Integrating Intune with Entra ID to enforce the right access controls at the right time Device Compliance — Configuring and troubleshooting compliance policies that feed into your security posture App Deployment — Win32 apps, LOB apps, Microsoft Store apps, and everything in between Troubleshooting — Diagnosing and resolving the Intune issues you’ll inevitably run into Connect # Feel free to reach out or follow along on LinkedIn and GitHub.\n","title":"About","type":"page"},{"content":" Get in Touch # Have a question, feedback, or just want to connect? Feel free to reach out.\nEmail # 📧 simon.pauly@paulycloud.com\nLinkedIn # 🔗 Simon Pauly Kofoed Mose\nGitHub # 🐙 spkm95\n","externalUrl":null,"permalink":"/contact/","section":"PaulyCloud — Intune \u0026 Endpoint Management Blog","summary":"Get in Touch # Have a question, feedback, or just want to connect? Feel free to reach out.\nEmail # 📧 simon.pauly@paulycloud.com\nLinkedIn # 🔗 Simon Pauly Kofoed Mose\nGitHub # 🐙 spkm95\n","title":"Contact","type":"page"},{"content":" We Do Not Collect Your Data # PaulyCloud is a personal blog. Your privacy matters, and this site is designed to respect it fully.\nNo Tracking # No cookies — This site does not set any cookies No analytics — No Google Analytics, no tracking pixels, no telemetry No fingerprinting — No browser or device fingerprinting of any kind No Data Collection # No personal data is collected, stored, or processed No email addresses are harvested or stored No user accounts are required No forms collect or transmit data from this site No Third-Party Trackers # This site does not embed any third-party tracking scripts, ad networks, or social media trackers.\nHosting # This site is hosted on Azure Static Web Apps. Azure may collect basic server logs (IP address, request timestamps) as part of standard web hosting operations. These logs are managed by Microsoft and are not accessed or stored by PaulyCloud. See Microsoft\u0026rsquo;s Privacy Statement for details.\nExternal Links # This site may contain links to external websites. PaulyCloud has no control over the content or privacy practices of those sites.\nContact # For privacy-related questions, contact simon.pauly@paulycloud.com.\n","externalUrl":null,"permalink":"/privacy/","section":"PaulyCloud — Intune \u0026 Endpoint Management Blog","summary":"We Do Not Collect Your Data # PaulyCloud is a personal blog. Your privacy matters, and this site is designed to respect it fully.\nNo Tracking # No cookies — This site does not set any cookies No analytics — No Google Analytics, no tracking pixels, no telemetry No fingerprinting — No browser or device fingerprinting of any kind No Data Collection # No personal data is collected, stored, or processed No email addresses are harvested or stored No user accounts are required No forms collect or transmit data from this site No Third-Party Trackers # This site does not embed any third-party tracking scripts, ad networks, or social media trackers.\n","title":"Privacy Policy","type":"page"},{"content":"","externalUrl":null,"permalink":"/search/","section":"PaulyCloud — Intune \u0026 Endpoint Management Blog","summary":"","title":"Search","type":"page"}]