feat(mdm): add supervised passcode and Screen Time management commands#778
Open
aluedeke wants to merge 6 commits into
Open
feat(mdm): add supervised passcode and Screen Time management commands#778aluedeke wants to merge 6 commits into
aluedeke wants to merge 6 commits into
Conversation
Three new supervised commands under `ios mdm`: - fetch-unlock-token: saves the device passcode unlock token to a file (device must have no passcode set; run once during provisioning) - clear-passcode: removes the device lock passcode using a saved token - clear-screen-time-password: clears the Screen Time restrictions PIN (no token required; supervisor identity alone suffices) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fetch-unlock-token --output=- prints the token as base64 to stdout instead of writing a file, making it easy to pipe into a secrets manager. clear-passcode --token=- reads a base64-encoded token from stdin. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drop *Supervised wrappers. Library methods (FetchUnlockToken, ClearPasscode, ClearScreenTimePassword) now operate on an already-escalated connection. CLI handler escalates once upfront and calls the clean API methods. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EscrowBag is absent from the pair response when the device is locked, causing a nil interface assertion panic. Use comma-ok and treat a missing EscrowBag as non-fatal — the existing pair record in usbmuxd remains valid and passcode clearing uses the separately stored unlock token. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When the device has a passcode, it accepts the supervisor identity but cannot update its trust store or return a new EscrowBag. Saving a new pair record (with freshly generated certificates) corrupts the existing valid record in usbmuxd — subsequent operations fail because the device still expects the original provisioning certificates. Skip savePair when EscrowBag is absent; the existing pair record remains valid for MCInstall and all other services. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously returned cleanly (exit 0) on mount error, silently bypassing set -e in launch.sh and letting the pod continue with no testmanagerd. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three new subcommands under
ios mdmfor supervised device passcode management via the MCInstall escalation channel:ios mdm fetch-unlock-token— saves the device passcode unlock token to a file; must be run while the device has no passcode set (typically during provisioning)ios mdm clear-passcode— removes the device lock passcode using a previously saved unlock token; works regardless of current lock state and without knowing the passcodeios mdm clear-screen-time-password— clears the Screen Time restrictions PIN; no token required, supervisor identity alone sufficesAll three commands require a supervised device and a PKCS#12 supervisor identity (
--p12file+--passwordorP12_PASSWORDenv var).Protocol background
The device lock passcode flow is a two-step MCInstall protocol (discovered by reverse engineering
MobileDeviceKit.frameworkfrom Apple Configurator 2):RequestUnlockToken→ device returns a ~1300-byte keybag escrow blob (only works when no passcode is set)ClearPasscode+UnlockToken→ clears the passcode (works even when device is locked)The Screen Time command is a single MCInstall
ClearRestrictionsPasswordrequest with no additional token required.New MCInstall methods
FetchUnlockToken() ([]byte, error)— on an already-escalated connectionFetchUnlockTokenSupervised(p12bytes, password)— escalates then fetchesClearPasscodeSupervised(p12bytes, password, token)— escalates then clearsClearScreenTimePasswordSupervised(p12bytes, password)— escalates then clears Screen Time PINTest plan
ios mdm fetch-unlock-token --p12file=<file> --password=<pw> --output=/tmp/token.binon a passcode-free supervised device → file written, JSON{"bytes":1304,"path":"..."}printedios mdm clear-passcode --p12file=<file> --password=<pw> --token=/tmp/token.bin→{"status":"ok"}, passcode goneios mdm fetch-unlock-tokenon a device with passcode set → exits 1 withDMCKeybagErrorDomainerrorios mdm clear-screen-time-passwordon a device with Screen Time PIN →{"status":"ok"}, PIN cleared🤖 Generated with Claude Code