Last Updated on March 24, 2026 by Oktay Sari
You have read the CIS benchmark. You have gone through BIO (Baseline Informatiebeveiliging Overheid). Maybe you even run the mSCP compliance audit. The recommendations are clear: disable iCloud Desktop & Documents Sync, disable AirDrop, block Apple Intelligence, turn off Siri. The controls exist, the profiles are straightforward, and the remediation playbook writes itself.
So you deploy the restriction policy to a pilot group and what do you know…within an hour, your help desk lights up. That happens when you skip macOS impact analysis.
A user had 44 GB of files synced through iCloud Desktop & Documents. When allowCloudDesktopAndDocuments was set to false, the user lost access to those files in Finder. Another user’s team relies on Writing Tools for proofreading client communications. That stopped working the moment allowWritingTools was blocked. A third user had AirDrop set to Everyone because they regularly receive files from external partners in the same building. Now they are filing a workflow disruption ticket.
None of these are edge cases. They are the everyday reality of enforcing security restrictions on a macOS fleet where people actually use their devices.
There is always a gap between “what should be restricted” and “what is safe to restrict right now.” That gap is filled with data you do not currently have.
In this post, I’ll walk you through a macOS impact analysis toolkit I built for Intune. Seven bash scripts, a PowerShell reporter, and an interactive HTML dashboard that shows you exactly which devices will be impacted by enforcement. Before you push the policy.
And as always…the cowboy that I am… Saddle up, grab those scripts, and ride out. Because in this rodeo, the only acceptable surprise is a clean compliance report. 🤠
What the Toolkit Covers
The toolkit consists of 7 bash scripts deployed as Intune custom attributes, covering services across 3 categories:
| Category | Scripts | Compliance Mapping |
| iCloud Services | Documents & Desktop Sync, Doc Sync, Keychain Sync | BIO 7.1/7.2/7.3, CIS 2.1.1.1/2.1.1.3 |
| Sharing Services | AirDrop, AirPlay Receiver | CIS 2.3.1.1/2.3.1.2 |
| AI & Assistant | Apple Intelligence, Siri | CIS 2.5.1.x/2.5.2.x |
For each service, the report uses a simple traffic light:
- Amber = the service is active and the user will be impacted
- Green = a managed profile already restricts this service
- Gray = the service is not in use, so enforcement is safe
- Red = error state (rare, typically script execution failures)
- Light gray = unknown state (no user logged in, home directory temporarily unavailable)
The data is anonymized. No filenames, no email addresses, no file contents. Device level metrics only.
You do not need to deploy all 7 scripts. The report adapts to what you deploy. Start with the category that matters most for your current enforcement timeline.
How the macOS Impact Analysis Works: Three Layers
Layer 1: Shell Scripts (On Device Detection)
Seven bash scripts, each deployed as an Intune custom attribute. They run on each Mac every 8 hours, detect the current state of a specific service, and output a compact pipe delimited string that Intune stores as the custom attribute result.
Almost every script follows the same pattern:
- Identify the logged in user via stat -f “%Su” /dev/console
- Check managed preference (is a profile already blocking this?). If yes, output BlockedByProfile and exit immediately
- Resolve home directory. If missing, retry once after 5 seconds (this handles login race conditions)
- If the home directory is still unavailable, output a degraded result with Unknown fields and exit
- Check user level settings (is the feature active?)
- Output a single line: Status|Key:Value|Key:Value|…
The managed preference check (step 2) uses NSUserDefaults.initWithSuiteName, which is system wide and does not require the user’s home directory. By checking it first, devices with unavailable home directories still report the most important information: whether a profile already manages the feature. As a result, this eliminates opaque error states and replaces them with actionable data.
The scripts run as root but detect the console user to read user level preferences. Output stays compact by design, well within Intune’s 20 KB result limit.
Here’s a simplified look at the detection logic for Desktop & Documents Sync:
# Check if a managed profile already blocks the feature
managedValue=$(/usr/bin/osascript -l JavaScript -e \
'$.NSUserDefaults.alloc.initWithSuiteName("com.apple.applicationaccess")
.objectForKey("allowCloudDesktopAndDocuments").js' 2>/dev/null)
# Measure folder sizes (follow symlinks)
desktopSizeMB=$(du -smL "$iCloudDesktop" 2>/dev/null | awk '{print $1}')
This JXA NSUserDefaults.initWithSuiteName approach is the same method used by mSCP. It works regardless of execution context because managed preferences from MDM profiles are system wide.
Layer 2: PowerShell Reporter (Graph API Aggregation)
Get-macOSServiceReport.ps1 connects to Microsoft Graph API, fetches the device run states for each deployed custom attribute script, and builds a JSON data blob containing the script registry, category definitions, and all device results.
# Default - all categories
.\Get-macOSServiceReport.ps1
# iCloud services only
.\Get-macOSServiceReport.ps1 -Categories icloud
# Non-interactive (for automation)
.\Get-macOSServiceReport.ps1 -Force -NoBanner
Layer 3: HTML Report (Browser Rendered Dashboard)
The JSON blob is injected into a self-contained HTML file. JavaScript renders everything: category switching, summary cards, the data table, filtering, sorting, search, pagination, and CSV export. No external dependencies. Open the file in any browser and the report works.
The HTML file is the deliverable. Send it to your CISO, attach it to a change request, archive it for audit evidence. It is a single file with everything embedded.
NOTE: Filters within the same card combine with OR (show Disabled or Blocked by Profile). Filters across different cards combine with AND (show devices that match both).
The 7 Detection Scripts: What They Find
You can download the toolkit form my GitHub Repository: macOS Service Impact Analysis
iCloud Desktop & Documents Sync
This is the big one. When enabled, macOS syncs the user’s Desktop and Documents folders to iCloud. The script checks for sync folders at ~/Library/Mobile Documents/com~apple~CloudDocs/. Because macOS creates symlinks (not copies) for this sync, du -smL (follow symlinks) is required to measure actual data size.
Example output: Enabled|Desktop:44.16gb|Documents:15.19gb|Optimize Storage:Yes|Setting Managed:No
If you enforce allowCloudDesktopAndDocuments=false on that device without warning, those files disappear from Finder. Nearly 60 GB of working files, gone. However, when a profile already blocks the feature, the script reports BlockedByProfile|Desktop:N/A|Documents:N/A|… without needing to access the home directory at all. This is exactly why you run impact analysis first.

iCloud Drive / Document Sync
iCloud Drive covers the broader document sync, including app containers for Pages, Numbers, Keynote, and third party apps. The script deliberately subtracts Desktop & Documents folder sizes to avoid double counting. These are separate compliance controls (BIO 7.1 vs. BIO 7.3), so the data should not overlap.
The script distinguishes between Active (containers exist with data), Configured (containers exist but empty), Inactive (no containers found), and BlockedByProfile (managed preference blocks it).
Example output: Active|Size:2.50gb|Optimize Storage:No|Setting Managed:No
When blocked: BlockedByProfile|Size:N/A|Optimize Storage:N/A|Setting Managed:Yes

iCloud Keychain Sync
iCloud Keychain is enabled by default when a user signs into iCloud. It’s opt out, not opt in. Unfortunately, macOS does not expose a reliable API to confirm Keychain status directly. Instead, the script uses inference: if iCloud is active and no profile blocks it, it’s almost certainly enabled. It reports LikelyEnabled to make this inference transparent.
Example output: LikelyEnabled|iCloud Account:Yes|Setting Managed:No
When blocked: BlockedByProfile|iCloud Account:N/A|Setting Managed:Yes
AirDrop
AirDrop uses Bluetooth LE for discovery and TLS for transfer. The CIS benchmark recommends disabling it because an active receiver advertises the Mac on the local network. The script reads DiscoverableMode from com.apple.sharingd.plist to report Off, Contacts Only, or Everyone. A device with “Everyone” is therefore a higher priority target.
Example output: Enabled|Discovery:Everyone|Setting Managed:No
When blocked: BlockedByProfile|Discovery:N/A|Setting Managed:Yes
AirPlay Receiver
AirPlay Receiver was introduced in macOS Monterey (12.0) and is enabled by default. The script reads AirplayRecieverEnabled from com.apple.controlcenter. Yes, that’s Apple’s own typo (“Reciever”). The script uses the misspelled key because that’s what macOS actually reads.
Example output: Enabled|Setting Managed:No
Apple Intelligence & Writing Tools (CIS 2.5.1.1 through 2.5.1.4)
The CIS macOS Benchmark recommends disabling all Apple Intelligence features at Level 1. The script checks five managed preference keys in a single pass:
| Key | Feature |
| allowWritingTools | Writing Tools (rewrite, proofread) |
| allowMailSummary | Mail Summarization |
| allowNotesTranscriptionSummary | Notes Summarization |
| allowExternalIntelligenceIntegrations | External AI (ChatGPT etc.) |
| allowExternalIntelligenceIntegrationsSignIn | Sign in to external AI |
Example output: PartiallyManaged|WT:Yes|Mail:Yes|Notes:No|ExtAI:No|Setting Managed:Partial
Siri
The CIS benchmark recommends disabling Siri entirely. The “Listen for Siri” feature (VoiceTriggerUserEnabled) is a per user preference that you cannot currently disable via MDM profile or plist. That’s why CIS 2.5.2.2 is classified as Manual.
The script checks both: whether Siri is enabled (via allowAssistant) and whether the always on microphone is active. That second data point is gold for building your business case.
Example output: Enabled|ListenFor:Yes|Setting Managed:No
When blocked: BlockedByProfile|ListenFor:N/A|Setting Managed:Yes
Deploying the Impact Analysis Scripts in Intune
- In the Intune admin center, navigate to Devices > macOS > Custom attributes
- Create a new custom attribute for each script
- Upload the .sh file and set Data type to String
- Use the exact display names below (the reporter matches on these)
iCloud Services:
- macOS – iCloud Desktop Documents Sync
- macOS – iCloud Document Sync
- macOS – iCloud Keychain Sync
Sharing Services:
- macOS – AirDrop Status
- macOS – AirPlay Receiver Status
AI & Assistant:
- macOS – Apple Intelligence Status
- macOS – Siri Status
Pro tip: Custom attribute scripts run every 8 hours on the Intune check in schedule. You cannot change the frequency, and you cannot run them on demand. Give it time for devices to report back before generating the report.
Use the exact names listed above when creating your custom attributes in Intune, and the reporting script will find them without any extra configuration.
But if you already deployed them with different names (maybe you had a creative naming day at the ranch), you don’t have to go back and rename everything. The script accepts override parameters so you can tell the cowboy what you actually named your horses: 🤠
.\Get-macOSServiceReport.ps1 -KeychainSyncName “Custom – My Fancy Name”
You can override one, two, or all three names. The parameters are -DesktopDocsSyncName, -DocumentSyncName, and -KeychainSyncName.
When you deploy these scripts as custom attributes in Intune, the display names matter. The PowerShell reporting script (Get-macOSServiceReport.ps1) uses those names to find the right results. It pulls all your custom attribute scripts from Intune via Graph API and then matches them by display name. No match means no data in your report. Use the exact names listed above when creating your custom attributes in Intune, and the reporting script will find them without any extra configuration. But if you already deployed them with different names (maybe you had a creative naming day at the ranch), you don’t have to go back and rename everything. The script accepts override parameters so you can tell the cowboy what you actually named your horses: 🤠 .\Get-macOSServiceReport.ps1 -KeychainSyncName “Custom – My Fancy Name” You can override one, two, or all three names. The parameters are -DesktopDocsSyncName, -DocumentSyncName, and -KeychainSyncName.
Pro tip: Save yourself the headache and just use the default names from the start. Future you will thank present you. 😅
The Enforcement Workflow
You can run this toolkit before every enforcement wave:
- Deploy detection scripts 1 to 2 weeks before the planned enforcement date
- Run the reporter to get the current state
- Share the HTML report with the project team
- Identify high impact devices (large iCloud data, active services)
- Communicate with affected users: “You have 44 GB synced to iCloud Desktop. We are restricting this on [date]. Please migrate your files.”
- Re run the reporter after communication to measure progress
- Enforce the restriction profile with confidence
The report is also valuable as audit evidence. “We assessed the impact on 487 devices. 73 had active iCloud Desktop sync. All 73 were notified. Data migration was confirmed for 71. Two devices were excluded from the initial enforcement wave pending migration.”
That is the difference between “we deployed the policy” and “we deployed the policy responsibly.”
Bridging the “Who Owns This Mac?” Gap
Now, the eagle-eyed readers among you might have noticed something. Step 5 says “communicate with affected users,” but the report only shows device names. No usernames, no email addresses. That’s by design. Privacy matters, and you don’t want user identities floating around in HTML reports that get shared across project teams. 🔒
But that does leave you with a “who the heck owns this Mac?” problem when you need to actually reach out. So here are two ways to bridge that gap:
Enhance the PowerShell script. The Graph API call already hits the managedDevice object. It currently only pulls deviceName and id, but you could expand that to include userPrincipalName. Think of it as an -IncludeUserInfo switch that adds a UPN column to the CSV export, while keeping it out of the HTML report. Best of both worlds: your project team gets a clean, privacy-friendly overview, and you get the contact details where you need them.
Use a separate Graph query. Filter the CSV for your high-impact devices (the ones with 44 GB synced to Desktop, for example), and then run a quick Graph query to batch-resolve the primary users. This approach keeps the detection scripts completely privacy-friendly while still giving you what you need for communication. Think of it as keeping the cattle brand registry in a separate book from the ranch map. 🤠
Either way, the point is: plan for this step before enforcement day. The report tells you which devices will be impacted. Figuring out who to notify is your next move. And who knows, I might just add that -IncludeUserInfo switch to the script in a future update. Stay tuned. 🤠
Compliance Reference
| Script | BIO | CIS Benchmark | mSCP Rule |
| Desktop & Documents | 7.3 | 2.1.1.3 (Level 2) | icloud_sync_disable |
| Document Sync | 7.1 | — | icloud_drive_disable |
| Keychain Sync | 7.2 | 2.1.1.1 (Level 2) | icloud_keychain_disable |
| AirDrop | — | 2.3.1.1 (Level 1) | os_airdrop_disable |
| AirPlay Receiver | — | 2.3.1.2 (Level 1) | system_settings_airplay_receiver_disable |
| Apple Intelligence | — | 2.5.1.1 through 2.5.1.4 (L1) | — |
| Siri | — | 2.5.2.1 (L1) / 2.5.2.2 (Manual) | system_settings_siri_disable |
Requirements and Prerequisites
- Intune with macOS devices enrolled (devices must run macOS 12.0 or later)
- Microsoft Graph PowerShell module: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
- Graph API permissions: DeviceManagementConfiguration.Read.All and DeviceManagementManagedDevices.Read.All
Privacy and Security Considerations
- No PII collected. No filenames, no email addresses, no file contents, no usernames. Device level metrics only.
- Folder sizes, not contents. The scripts measure how much data is at risk, not what that data is.
- Boolean flags, not details. Is Siri enabled? Yes or No. Is “Listen for Siri” active? Yes or No.
- Scripts run as root (Intune custom attributes always do) but detect the logged in console user to read user level preferences.
- The JSON data blob exists only in memory during PowerShell execution. It persists only in the HTML output file, which you control.
Don’t Just Trust Any Script
ALWAYS TEST these scripts in a controlled environment before deploying them across your production fleet! Don’t just trust any script you find on the internet. Try to really understand what it does. Read through the scripts. They’re well commented. Check the shellcheck and PSScriptAnalyzer results.
Wrapping Up
Implementing security restrictions is an important part of hardening your macOS fleet. Whether it’s iCloud services, AirDrop, Siri, or Apple Intelligence, every one of these features exists because users find value in it. Disabling them blindly is like throwing a surprise party where the surprise is that everyone’s tools are gone.
With this toolkit, you get the data you need to make informed rollout decisions. You’ll know exactly which devices are affected, how much data is at risk, and where you already have coverage. And the pattern scales to any macOS feature any benchmark recommends restricting.
Resources
- GitHub Repository: macOS Service Impact Analysis
- Microsoft Intune: Shell Scripts and Custom Attributes for macOS
- CIS Apple macOS Benchmarks
- mSCP (macOS Security Compliance Project)
- BIO (Baseline Informatiebeveiliging Overheid)
- Microsoft Graph API Reference




