Auto-Remediating FileVault Recovery Key Escrow Failures
Detect and auto-remediate missing FileVault recovery key escrow on managed Macs using Jamf Pro or Intune before it becomes a lockout ticket.

Operational brief
Operational outcome
Detect and auto-remediate missing FileVault recovery key escrow on managed Macs using Jamf Pro or Intune before it becomes a lockout ticket.
Target Tier
L2 support
Implement within an approved test scope before wider deployment.
Time to set aside
About 35 minutes
Includes configuration, validation and deployment.
Tutorial navigation
#The Old Way vs the New Way
The old way looks like this: a user forgets their Mac password on a Monday morning, the MDM console shows a recovery key on file, the technician retrieves it, types it in over a screen-share, and it fails. The key on file was generated before the last password change, or the FileVault Recovery Key Redirection profile silently failed to escrow after a macOS upgrade, or the Mac enrolled before the profile was ever scoped to it. The technician now has an angry user, a locked drive, and no working key. The only remaining option is a full data wipe and re-image, which turns a five-minute unlock into a half-day incident.
The new way treats recovery key escrow as a fleet health signal, not a support ticket. Managed Macs report their escrow status back to inventory on a schedule. Any Mac where the individual recovery key is missing, invalid, or unverified is automatically flagged, silently remediated by forcing a key rotation and re-escrow, and re-verified against the MDM server before the user ever notices. Technicians only get paged when automated remediation fails twice in a row, which is the genuine escalation-worthy event.
#Prerequisites and Permissions
- Jamf Pro 10.x or later, or Microsoft Intune with the macOS platform enabled, and an enrolled fleet using Automated Device Enrolment via ABM.
- A deployed configuration profile containing the
com.apple.security.FDERecoveryKeyEscrowpayload, scoped to all managed Macs, so that personal recovery keys generated locally are automatically redirected to the MDM server. - Jamf Pro API role with Read on Computers and Computer Inventory, plus Update permission scoped to a dedicated API client (not an admin’s personal account) for the compliance query script.
- Script deployment capability: a Jamf Pro policy with a custom script payload, or an Intune Shell Script configuration profile with the Run as, and Run script as signed-in user options set to root.
- A device is only in scope for remediation if
fdesetup statusreports FileVault as On. Never target unencrypted Macs; that is a separate enablement workflow. - Local admin execution context: the remediation script must run as root during a check-in or Self Service session while a volume owner with a valid Secure Token is logged in, per Apple’s documented FileVault deployment behaviour.
#Implementation Steps
- Deploy the recovery key redirection profile. Action: push a configuration profile containing the
com.apple.security.FDERecoveryKeyEscrowpayload to all managed Macs via Jamf Pro Configuration Profiles or an Intune custom profile. Expected result: every Mac that later generates or rotates a personal FileVault key automatically transmits it to the MDM server instead of only displaying it locally. Evidence: profile shows as “Installed” in device inventory;profiles showoutput on a test Mac lists the FDERecoveryKeyEscrow payload identifier. - Deploy an inventory Extension Attribute (Jamf) or custom compliance script (Intune). Action: create a script-based Extension Attribute that checks local FileVault state and profile presence, and report the result at every inventory update. Expected result: every managed Mac contributes a fresh status string on each check-in cycle. Evidence: the Extension Attribute value populates in the computer inventory record within one check-in cycle of deployment.
- Build the server-side compliance query. Action: run a scheduled script against the Jamf Pro API
computers-inventoryendpoint, filtering on thediskEncryption.individualRecoveryKeyValidityStatusfield for values other thanVALID. Expected result: a machine-readable list of Macs with missing, unknown, or invalid escrowed keys. Evidence: script output log with serial numbers and status values, timestamped. - Scope a Smart Group (Jamf) or dynamic device group (Intune) to the non-compliant population. Action: build a Smart Group using the Extension Attribute value “Escrow Profile Missing” or “Key Status Unknown”. Expected result: the group membership updates automatically as devices drift in and out of compliance. Evidence: Smart Group membership count visible in Jamf Pro console, matching the API query result count within one inventory cycle.
- Deploy the remediation policy. Action: scope a Jamf Pro policy (or Intune shell script assignment) containing the rotation script to the non-compliant Smart Group, triggered on check-in with a frequency of “once per day until it runs successfully”. Expected result: the personal recovery key is regenerated and re-escrowed without user interaction. Evidence: policy log shows exit code 0; local remediation log file shows a successful rotation timestamp.
- Fire a webhook notification on remediation outcome. Action: the remediation script posts a JSON payload to a monitoring webhook (Slack, Teams, or a ticketing system’s inbound API) reporting success or failure. Expected result: a real-time signal lands in the operations channel without anyone opening the MDM console. Evidence: webhook delivery log entry with HTTP 200 response and matching serial number.
- Re-verify escrow status. Action: re-run the compliance query 24 hours after remediation to confirm the device has moved from a non-compliant to a compliant state. Expected result:
individualRecoveryKeyValidityStatusreadsVALIDfor the remediated serial number. Evidence: diff of the before/after API query output showing the status transition.
#Detection Extension Attribute Script
Deploy this as a Jamf Pro Extension Attribute (script input type) so escrow health becomes a queryable inventory field rather than something a technician has to remember to check manually.
1#!/bin/bash
2# Extension Attribute: FileVault Escrow Health
3# Reports whether FileVault is on and whether the redirection
4# profile that forces personal key escrow to MDM is installed.
5
6FV_STATUS=$(fdesetup status)
7PROFILE_COUNT=$(profiles show -output stdout-xml 2>/dev/null | grep -c "com.apple.security.FDERecoveryKeyEscrow")
8
9if [[ "$FV_STATUS" != *"FileVault is On"* ]]; then
10 echo "<result>FileVault Not Enabled</result>"
11elif [[ "$PROFILE_COUNT" -eq 0 ]]; then
12 echo "<result>Escrow Profile Missing</result>"
13else
14 echo "<result>Escrow Profile Present</result>"
15fiExpected output on a healthy Mac: Escrow Profile Present. On a Mac missing the redirection profile: Escrow Profile Missing, which should immediately place it in the remediation Smart Group.
#Server-Side Compliance Query
This script queries the Jamf Pro API for the authoritative, server-verified escrow status. Local checks confirm the profile is installed; only the server can confirm the key actually arrived and validated.
1import requests
2
3JAMF_URL = "https://yourinstance.jamfcloud.com"
4CLIENT_ID = "YOUR_API_CLIENT_ID"
5CLIENT_SECRET = "YOUR_API_CLIENT_SECRET"
6
7def get_token():
8 resp = requests.post(
9 f"{JAMF_URL}/api/oauth/token",
10 data={
11 "grant_type": "client_credentials",
12 "client_id": CLIENT_ID,
13 "client_secret": CLIENT_SECRET,
14 },
15 timeout=30,
16 )
17 resp.raise_for_status()
18 return resp.json()["access_token"]
19
20def find_noncompliant(token):
21 headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
22 params = {
23 "page": 0,
24 "page-size": 200,
25 "section": "DISK_ENCRYPTION,GENERAL",
26 }
27 resp = requests.get(
28 f"{JAMF_URL}/api/v1/computers-inventory",
29 headers=headers,
30 params=params,
31 timeout=30,
32 )
33 resp.raise_for_status()
34 results = []
35 for device in resp.json().get("results", []):
36 status = device.get("diskEncryption", {}).get(
37 "individualRecoveryKeyValidityStatus", "UNKNOWN"
38 )
39 if status != "VALID":
40 results.append(
41 {
42 "serialNumber": device["general"]["serialNumber"],
43 "name": device["general"]["name"],
44 "status": status,
45 }
46 )
47 return results
48
49if __name__ == "__main__":
50 token = get_token()
51 noncompliant = find_noncompliant(token)
52 for item in noncompliant:
53 print(item)Expected output for a fleet with two problem devices: two dictionary lines printed, each containing a serial number and a status of INVALID or UNKNOWN. An empty output means the fleet is fully compliant.
#Remediation Script
Deploy this via a Jamf policy or an Intune shell script scoped only to the non-compliant group. It rotates the personal recovery key, which forces the redirection profile to push the new key to the MDM server immediately.
1#!/bin/bash
2# FileVault Recovery Key Remediation
3# Scope: devices flagged with Escrow Profile Missing or invalid key status
4LOGFILE="/var/log/filevault-key-remediation.log"
5TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
6
7FV_STATUS=$(fdesetup status)
8
9if [[ "$FV_STATUS" != *"FileVault is On"* ]]; then
10 echo "$TIMESTAMP SKIP: FileVault not enabled on this device" >> "$LOGFILE"
11 exit 1
12fi
13
14# Rotate the personal recovery key. The redirection profile installed
15# in Step 1 forces the new key to escrow to the MDM server automatically.
16ROTATE_OUTPUT=$(fdesetup changerecovery -personal -outputplist 2>&1)
17ROTATE_EXIT=$?
18
19if [[ "$ROTATE_EXIT" -eq 0 ]]; then
20 echo "$TIMESTAMP SUCCESS: recovery key rotated, awaiting escrow confirmation" >> "$LOGFILE"
21else
22 echo "$TIMESTAMP FAILURE: $ROTATE_OUTPUT" >> "$LOGFILE"
23fi
24
25exit "$ROTATE_EXIT"Expected output in the log file on success: SUCCESS: recovery key rotated, awaiting escrow confirmation. A non-zero exit code should trigger the webhook failure branch described below rather than being silently retried indefinitely.
#Webhook Notification Payload
Append this call to the end of the remediation script so operations channels get a real-time signal instead of relying on someone opening the console.
1curl -s -X POST "https://hooks.example.com/services/ops-alerts"
2 -H "Content-Type: application/json"
3 -d '{"text":"FileVault key remediation event","serialNumber":"'"$(system_profiler SPHardwareDataType | awk '/Serial/{print $4}')"'","status":"'"$ROTATE_EXIT"'","timestamp":"'"$TIMESTAMP"'"}'Example JSON body received by the webhook endpoint:
1{
2 "text": "FileVault key remediation event",
3 "serialNumber": "C02XG1234ABC",
4 "status": "0",
5 "timestamp": "2024-05-01 09:14:02"
6}#Verification and Expected Evidence
| Check | Method | Expected Evidence |
|---|---|---|
| Profile installed | profiles show on device | FDERecoveryKeyEscrow payload identifier listed |
| Local FileVault state | Extension Attribute value in inventory | “Escrow Profile Present” |
| Server-side key validity | Jamf Pro API computers-inventory query | individualRecoveryKeyValidityStatus equals VALID |
| Remediation execution | Policy log or Intune script run status | Exit code 0, log entry with SUCCESS string |
| Alerting | Webhook delivery log | HTTP 200 response matching device serial number |
#Rollback
Recovery key rotation is non-destructive: it does not touch encrypted data, does not require a reboot, and does not remove the existing institutional key if one is present. There is no data to roll back. If the redirection profile itself causes unexpected behaviour, such as conflicting with an existing institutional key deployment, remove the MDM configuration profile from the scope and unscope the remediation policy from the affected group. If a specific Mac reports repeated rotation failures, the safe rollback path is to fall back to the manual key retrieval process for that single device while it is investigated, rather than disabling the automation fleet-wide.
#Failure and Escalation Conditions
- The remediation script returns a non-zero exit code on two consecutive scheduled runs for the same serial number: escalate to L2 to check Secure Token and bootstrap token status with
diskutil apfs listUsers /. - The Jamf Pro API query returns
individualRecoveryKeyValidityStatusasUNKNOWNfor more than 5 percent of the fleet after 48 hours: escalate to the MDM platform owner, since this points at a systemic escrow pipeline issue rather than individual device drift. - A user reports a lockout and the escrowed key on file fails validation when tested against the device: this is the one condition that should wake a human technician immediately, regardless of time of day, since the user has no other path back into the device short of erase and reinstall.
- The webhook endpoint stops receiving events for more than one check-in cycle: treat as a monitoring blind spot and escalate to whoever owns the alerting integration, not the FileVault workflow itself.
#Measuring Ticket Deflection
Baseline the current volume of FileVault unlock and recovery key tickets over a rolling 90-day window before deployment. After rollout, track three numbers monthly: the count of devices in the non-compliant Smart Group at the start of each month, the percentage that self-remediate within one check-in cycle without a ticket being opened, and the count of tickets that still required manual key retrieval. A healthy deployment should show the non-compliant population trending toward zero and manual retrieval tickets dropping by at least 70 percent within the first full quarter, since the majority of prior tickets were caused by silent escrow failures rather than genuine user error.
#Blast Radius and Monitoring Signal
The blast radius of the remediation script is limited to key rotation on individually scoped, already-FileVault-enabled Macs; it never enables encryption on an unencrypted device and never modifies an institutional key. The monitoring signal to watch is the daily count of devices leaving the non-compliant Smart Group compared to the count entering it; a net positive inflow over several days indicates the redirection profile itself has stopped deploying correctly and needs review before the remediation script is blamed.
#References
For the underlying platform behaviour and API fields referenced in this workflow, see the Apple Platform Deployment Guide for FileVault and configuration profile management, and the Apple Developer documentation for Device Management payloads, which defines the FileVault recovery key escrow payload used in Step 1. For platform-specific implementation detail, consult the Jamf Pro documentation for FileVault 2 management and the Microsoft Intune documentation for macOS shell scripts if deploying the remediation logic through Intune instead of Jamf Pro.
Sources and verification
Vendor documentation and external technical references used by this playbook.
Advanced suggested reading
Ready to go deeper?
These articles come from KBY’s senior engineering editorial. Expect denser architecture, fewer introductory explanations and deeper production trade-offs.
Enterprise IT Management
Detecting Toxic Access with Graph-Based SoD Engines
How graph databases and OPA policy-as-code detect cross-system segregation of duties conflicts before toxic access grants ever commit.
Tech Fundamentals
Fixing UEFI Secure Boot Chain-of-Trust Failures
How PK, KEK, db, dbx, shim and MOK layers interact, and the mokutil, sbsign, and sbctl steps that repair a broken UEFI trust chain.
Comments
Add a thoughtful note on Auto-Remediating FileVault Recovery Key Escrow Failures. Comments are checked for spam and held for moderation before appearing.