macOS is steadily filling with XProtects. At the last count, there were three different XProtects, and one of those is doubled up as its data is now kept in two different places. This article tries to clear up any confusion over which is which, and what gets updated when.
The three different XProtects are:
- Plain and traditional XProtect, which works as part of Gatekeeper, to perform on-demand scans of code to check it for known malware before it’s run.
- A more recent background scanning service XProtect Remediator runs once a day, looking for signs of known malware and removing it if possible. This also relies on detection signatures included in regular XProtect bundles.
- The most recent XProtect Behavioural monitors for code that breaks its set of rules for sensitive locations and actions, and reports those back to Apple’s security intelligence.
As the ‘Bastion’ rules used by the third of those are contained in XProtect Remediator, the second, those two are updated together in a single bundle handled by the regular Software Update service. I won’t consider those any further here, as they’re relatively straightforward, and now updated infrequently.
XProtect
The first of those, plain on-demand XProtect, used to consist of a single bundle updated fairly frequently in a single location, in /Library/Apple/System/Library/CoreServices/XProtect.bundle, again by the normal Software Update service, as shown in the diagram below.

That changed in macOS Sequoia and later, where there’s also a copy of that bundle installed in /var/protected/xprotect/XProtect.bundle which is the one that’s used when XProtect checks code. That copy is updated and maintained separately: instead of using the regular Software Update service and Apple’s software update servers, it has its own background maintenance process that obtains its updates from a connection to iCloud. But the original XProtect still exists in its old location.
Macs running Sequoia and later thus have to maintain two copies of the XProtect bundle, in two different locations, using two separate mechanisms. While the old copy still relies on Software Update, the new one doesn’t.
New version release
When Apple releases an updated version of the XProtect bundle, it should provide that from both its software update servers and iCloud. In practice, the iCloud update may not appear as promptly as that on the update servers, so there may be a period in which the only XProtect that can be updated is in the old location. That can leave a Mac with the two copies using different versions.
The best way to deal with this is to:
- install the new version available through Software Update or SilentKnight, as offered;
- leave macOS to install a copy of the new version to its new location, or try to do this manually using the
xprotectcommand in Terminal.
Update mechanisms
If you left your Mac to find and install these two XProtect updates without intervention, this is what should happen:
- The background process
softwareupdatedruns a periodic check for software updates available from Apple’s servers, and finds that an XProtect update is available. It then downloads and installs that automatically to the old location. You can trigger this to take place using thesoftwareupdatecommand, or by running SilentKnight. - The background service
XProtectUpdateServiceruns a periodic check for XProtect updates available from the iCloud service; that doesn’t require your Mac to be signed into your Apple Account, or into iCloud. It finds a new XProtect update is available, so downloads and installs that automatically to the new location. You may be able to trigger this to take place using thexprotectcommand, but SilentKnight can’t do that (yet).
One perhaps subtle difference between these two is that automatic updates using Software Update can be disabled by turning off Install system data files and security updates in Software Update settings, but the user has no control over XProtectUpdateService.
SilentKnight
All compatible versions of my free app SilentKnight rely on softwareupdate to check for and install updates, although in Sequoia and later they report the version of XProtect found in the new location, which they don’t try to update. This means that installing an XProtect update using SilentKnight doesn’t alter the version it reports in Sequoia and later. When the version reported isn’t the current version available, you can choose whether to update it manually using the xprotect command, or to leave it to the background service XProtectUpdateService to perform automatically.
For SilentKnight to use the xprotect command itself requires a privileged helper app, and as I’ll explain below, that has remained in a state of flux since Sequoia. While the best solution continues to change, I have decided that the complication of adding a privileged helper isn’t a good choice, yet.
xprotect command tool
macOS Sequoia introduced a new command tool xprotect to give users maintenance access to XProtect in its new location. In this context there are three command options of value:
xprotect version, run at a normal privilege level, returns the version number and datestamp of its installation;xprotect check, run usingsudofor elevated privileges, returns the version number available from iCloud;xprotect update, run usingsudofor elevated privileges, initiates the download and installation of any higher version available from iCloud.
Since its introduction, the latter two options have changed in their effect. xprotect check can sometimes return an error, and has consistently done so in Golden Gate betas, making it impossible to check whether an update is available from iCloud. xprotect update has at times used any update already installed in the original location to install that to the new location, but doesn’t appear to do so currently, at least in some versions of macOS. Thus neither of those two command options can be relied on to behave consistently across Sequoia, Tahoe and Golden Gate. Until they do, it would be folly for SilentKnight to rely on them to check for and install XProtect updates to the new location.
Recommended actions
- If you’re content to let macOS keep your Mac up to date for XProtect, leave Software Update and XProtectUpdateService to detect, download and install updates when they’re released.
- If you want to take control and ensure XProtect updates are installed as promptly as possible, use SilentKnight or the
softwareupdatecommand tool to detect, download and install updates to the old location. When that is updated, runsudo xprotect checkin Terminal. If that indicates a new version is available from iCloud, runsudo xprotect updateto download and install it. If the first returns an error, ignore it and try to update regardless.
How xprotect works
The xprotect command tool is a front man for the background service XProtectUpdateService. Once the authentication has succeeded
03.354702 com.apple.opendirectoryd Authentication succeeded for [private] (D8A9D4E1-D214-40AD-B75C-F4E3C624BEB0): ODNoError
xprotect connects to the update service
03.362101 com.apple.xprotect Connecting to XProtectUpdateService
which is booted
03.372873 com.apple.security.XProtectFramework.XProtectUpdateService XProtectUpdateService booting
03.372956 com.apple.security.XProtectFramework.XProtectUpdateService XProtectUpdateService coming online: [private]
This designates a container for update purposes
03.377934 com.apple.security.XProtectFramework.XProtectUpdateService Using container ID com.apple.sear.xprotect-updates
and this is linked in with CloudKit and the update started
03.380143 com.apple.security.XProtectFramework.XProtectUpdateService Beginning update
An anonymous account is created for the purpose
03.388457 com.apple.cloudkit Created anonymous account
After a long series of network transactions, XProtectUpdateService finds and selects an update to install
03.658732 com.apple.security.XProtectFramework.XProtectUpdateService Selected [private] for installation
03.658745 com.apple.security.XProtectFramework.XProtectUpdateService Attempting to apply update: [private]
which is requested through CloudKit.
Each file in the update is then downloaded individually, chunked (as is standard with iCloud) and handled by MMCS (short for MobileMe Chunking Service, referring back to Apple’s subscription-based predecessor to iCloud of 2008-12), which declares each complete
03.995370 com.apple.mmcs Downloads complete. All done! (Get request 0x9b8e51800)
and the update file is created
04.053465 com.apple.security.XProtectFramework.XProtectUpdateService Creating update file @[private]
Once all the downloads have been completed, the update is activated
04.976584 com.apple.security.XProtectFramework.XProtectUpdateService Update completed. Activated update [private]
and the service shut down
04.977864 pid/978 [xprotect] removing active service: com.apple.XProtectFramework.UpdateService
When an XProtect scan is being started, the path to the XProtect bundle being used is reported in the log, for example
01.146410 com.apple.xprotect Using XProtect rules location: /var/protected/xprotect/XProtect.bundle/Contents/Resources/XProtect.yara
Why duplicate XProtect data?
Mere duplication would be inefficient and serve little purpose, but Apple doesn’t explain any of this apart from the glimpses provided by man xprotect. My guess is that the newer iCloud-based service and location will be served enhanced XProtect bundles to support additional services. The new AppProtectionPolicy property list is just a taste of what is to come for Apple silicon Macs running macOS 27 and later. But that’s pure speculation.
