Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5292. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version removes the macos_toydrop_b rule for MACOS.ADLOAD, and amends the rules for MACOS.ADLOAD.I, MACOS.BUNDLORE.MDPLST and MACOS.ADLOAD.IN.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5292.
Sequoia systems only
This update has now been released for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then enter your admin password. If that returns version 5292 but your Mac still reports an older version is installed, you can force the update using sudo xprotect update
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Each new version of macOS has increased the complexity of launching apps, from the basics of launchd, the addition of LaunchServices, to security checks on notarization and XProtect. This article steps through the major landmarks seen when launching a notarized app that has already passed its first-run checks and is known to macOS Sequoia 15.3, on an Apple silicon Mac.
Rather than trying to provide a blow-by-blow account of what’s written in the log over the course of thousands of entries, I’ve extracted landmarks that demonstrate when each subsystem gets involved and its salient actions. These have been gleaned from several similar app launches, and are ultimately timed and taken from one complete record of one of my simpler notarized apps that has no entitlements and uses only basic AppKit features. The app hadn’t been through quarantine as it had been built and notarized on the same Mac, and had been run previously but not in that session since the previous boot. It had thus been previously registered with LaunchServices and other subsystems. The host was a Mac mini M4 Pro, so timings should be briefer than on many other Macs, it was run from the main Applications folder on the internal SSD, and AI was enabled.
LaunchServices and RunningBoard
LaunchServices has been around for many years, and handles many of the tasks exposed in the Finder, including mapping of document types to app capabilities, Recent Items and Open Recent lists, making it the backbone of app launching. RunningBoard was introduced in Catalina and has steadily assumed responsibility for managing resources used by apps, including memory and access to the GPU. Although the test app doesn’t have any of its resources managed by RunningBoard, LaunchServices launched it through RunningBoard.
RunningBoard’s first task is to create a job description, which it helpfully writes to the log as a dictionary. This is a mine of useful information, and has replaced the copious information compiled by LaunchServices in the past. This includes:
a dictionary of Mach services
whether Pressured Exit is enabled
a full listing of environment variables, such as TMPDIR, SHELL, PATH
RunningBoard properties including another TMPDIR
whether to materialise dataless files.
Once that job description has been constructed for the app, RunningBoard tracks the app and its assertions, providing a detailed running commentary through the rest of the app’s life. LaunchServices still performs its traditional tasks, including creating an LSApplication object and sending an oapp AppleEvent to mark the opening of the app, and launchd still reports that it’s uncorking exec source upfront.
When the app is running, its preferences are loaded from the user CFPrefsD, and its pasteboard is created. Almost 0.1 second later (0.3 seconds after the start of launch) there’s a sustained flurry of log entries concerning Biome, and signs of AI involvement (Apple silicon only). The latter include a check for the availability of generative models and WritingTools. There are also entries referring to the loading of synapse observers.
LaunchServices log entries are readily accessed through its subsystem com.apple.launchservices, and RunningBoard through com.apple.runningboard.
Security and privacy
The first serious engagement in security is the verification of the app’s signature and its evaluation by Apple Mobile File Integrity (AMFI, using amfid). Shortly after that comes the standard Gatekeeper (GK) assessment, with its XProtect scan, starting less than 0.1 second after the start of launch. Immediately after the start of that scan, XProtect should report which set of data files it’s using. In Sequoia those should be at /var/protected/xprotect/XProtect.bundle/Contents/Resources/XProtect.yara. That scan took just over 0.1 second.
While XProtect is busy, syspolicyd checks the app’s notarization ticket online, through a CloudKit connection with the CKTicketStore. That’s obvious from log entries recording the network connections involved, and the complete check takes around 0.05 second. Once that and the XProtect scan are complete, syspolicyd reports the GK scan is complete, and evaluates its result.
At about the same time that the Gatekeeper checks are completing, privacy management by TCC (Transparency Consent and Control, in tccd) is starting up. Its initialisation includes establishing the Attribution Chain for any Mach-O binaries run by the app, so that TCC knows where to look for any required entitlements. Following that, TCC writes bursts of entries as different components such as the Open and Save Panel service are set up for the app.
The final phases of security initialisation come in provenance tracking, which first appeared in macOS Ventura. This may be associated with presence of the extended attribute com.apple.provenance, but details are currently sketchy.
Following syspolicy in the log is best through its subsystem com.apple.syspolicy, you can watch XProtect using com.apple.xprotect, and TCC is com.apple.TCC.
Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5291. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version amends the Yara rule for MACOS.PIRRIT.OBF.DROPPER, but doesn’t add any new rules.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5291.
Sequoia systems only
This update has also been released for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then enter your admin password. If that returns version 5291 but your Mac still reports an older version is installed, you can force the update using sudo xprotect update
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5290. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version adds a single new Yara rule for MACOS.SLEEPYSTEGOSAURUS.SYM.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5290.
Sequoia systems only
This update has just been released for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then enter your admin password. If that returns version 5290 but your Mac still reports an older version is installed, you can force the update using sudo xprotect update
Hurrah!
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Updated 1840 GMT 11 March 2025, announcing iCloud release!
Since XProtect Remediator (XPR) went live during the summer of 2022, it has run daily sets of checks for known malware in macOS Catalina and later using its scanning modules. Those have been sufficiently regular and reliable that some of my apps, including Skint and SilentKnight, check that they’re occurring and report normal and healthy results. Just over a month ago, I provided a detailed account of XPR’s different types of scan, and how they are scheduled and dispatched in XPR version 149. Last week in XPR version 151, Apple changed all that, and Skint, SilentKnight and XProCheck may now show few scans and frequent warnings.
As Apple has never provided anything other than the vaguest of information about XPR, I have no idea whether this is the new normal, or the result of bugs. As XPR scans now vary greatly between different Macs, and run least on those with large numbers of Time Machine backups accessible, I’m inclined to suspect at least some of this is unintended behaviour.
XPR scans
There are still three types of timed scan:
a fast scan, com.apple.XProtect.PluginService.agent.fast.scan, performed at intervals of 6 hours (21600 seconds), and run when on battery;
a standard scan, com.apple.XProtect.PluginService.agent.scan, performed at intervals of 24 hours (86400 seconds), but not run when on battery;
a slow scan, com.apple.XProtect.PluginService.agent.slow.scan, performed at intervals of 7 days (604800 seconds), but not run when on battery.
In the standard scan, each of the scanning modules is run in turn, once using the agent version running as the current user, normally 501, and once using the daemon version as root, user 0.
Fast scans do run every six hours, but don’t currently include any of the scanning modules, so leave little trace in the log. They are also run soon after starting up and logging in as a user, where they’re referred to as a startup scan when run as root, and a login scan when run as the current user, usually 501.
As a slow scan is only run once a week, I still haven’t been able to observe one.
With XPR version 151 installed, you’re likely to see the following sets of scans after user login:
Paired startup and login scans, no scanning modules used, taking about 46 seconds for root and 9 seconds for user 501.
Timed low priority scans as root and user, using just the Eicar scanning module, and taking about 2 and 1 seconds respectively.
Timed standard scans as root and user using all the scanning modules, and taking around 175 seconds for root, and up to 600 seconds as user. These may be cancelled by the XP Timer firing, which kills the current scanning module and terminates that set of scans, leaving them incomplete.
Thereafter, every six hours a fresh fast scan is performed, and every 24 hours a standard scan is attempted, although the latter may be terminated without completing any scanning modules at all.
XP Timer termination
At varying times after the start of a standard scan running its sequence of scanning modules, they may be interrupted by the firing of the XP Timer, and you’ll see a sequence of entries in the log describing how that not only kills the current scanning module, but terminates the whole of that set of scans: 16.438 com.apple.XProtectFramework 34294 XP Timer fired, killing activity
16.438 com.apple.XProtectFramework 34784 Received SIGTERM, canceling running plugins then exiting
16.439 XProtectRemediatorAdload Cancellation handler called for reason: Dispatch recieved SIGTERM
16.442 XProtectRemediatorAdload {"caused_by"[], "execution_duration":0.0002809762954711914, "status_message":"PluginCanceled", "status_code":30}
It’s that status_message and status_code that is detected by XProCheck, SilentKnight and Skint, and reported there as a warning.
16.450 com.apple.XProtectFramework Finished system scan, ran as 501
16.451 com.apple.duetactivityscheduler COMPLETED <_DASActivity: "501:com.apple.XProtect.PluginService.agent.scan:BD32B7", Utility, 60s, [09/03/2025, 07:39:13 - 10/03/2025, 07:39:13], Started at 09/03/2025, 19:52:35, Group: com.apple.dasd.default, Intensive: CPU Disk, PID: 2254>
16.453 com.apple.xpc.activity Rescheduling: com.apple.XProtect.PluginService.agent.scan (0x653344140)
16.457 com.apple.duetactivityscheduler Completed <private>, ran for 9.7 mins, total runtime 9.7 mins
The next daily standard set of scans are then submitted to DAS for rescheduling, to be run in about 24 hours: 16.465 com.apple.duetactivityscheduler Submitted: 501:com.apple.XProtect.PluginService.agent.scan:15B497 at priority 30 with interval 86400 (Mon Mar 10 07:52:34 2025 - Tue Mar 11 07:39:13 2025)
Although referred to as the XP Timer, times when it will fire range widely, from a few seconds to nearly ten minutes, and there’s no indication of how that is determined.
Effects
XPR checks now differ greatly between Macs. Most basic systems running from their internal SSD with a minimum of external storage, with just a modest set of Time Machine backups, still appear to complete standard scans normally, as they did in previous versions of XPR.
Macs with multiple external disks and long series of Time Machine backups may now complete few if any standard scans. Instead, most or all of them are terminated prematurely by the XP Timer, so triggering warnings in XProCheck, SilentKnight and Skint.
If you wish to run a set of XPR scans manually, then you still can, either in XProCheck or by running the XProtect app yourself. Those are run as the current user, not as root, but may be sufficient to restore your confidence in XPR’s protection.
This leaves me with a dilemma: should those apps suppress those warnings and tell you that everything is fine with XPR’s checks, or should they continue to report them? Given all the problems with XProtect updates in Sequoia, would it be simplest just to abandon my attempts to check anything in macOS security? Are these bugs, and should they be reported to Apple, or is this the new normal we have to look forward to for the future?
Over the last nine years, few of my articles here have been about XProtect, other than those announcing its updates. Until September 2024 and the release of macOS 15 Sequoia. This is now the tenth article I have written about the problems brought by XProtect updates in Sequoia over those six months, when there have been just 13 updates. The result of the last, on 4 March, was that for two days afterwards, many Macs running Sequoia were still using its data from 26 February rather than that in the new version 5289.
This not only affects XProtect, but the other front-line tool in macOS to detect and remove malicious software, XProtect Remediator (XPR). Earlier this year, I reported that at least 17 of the 24 scanning modules in XPR now use Yara definitions provided by XProtect’s data. All those Macs still running the superseded version of XProtect would also have had XPR scans run using that old version of the Yara rules.
XPR is a recent addition to these tools, introduced just three years ago, but XProtect goes way back before Yosemite in 2014. Although there have been occasional brief glitches in delivery of its updates, they have almost invariably completed quickly and reliably, leaving very few Macs stuck with an outdated version 24 hours after an update.
I have now come to dread XProtect updates because of the problems we encounter, and the latest update to 5289 was a good example. There’s a flurry of comments and emails from those whose Macs had failed to complete the update, previously a rare exception. For XProtect 5287 on 5 February, for example, there were 33, including my responses. For version 2184 exactly a year earlier there’s not one comment about that XProtect update.
Sole documentation provided about XProtect’s updates in Sequoia is the man file for its command tool, xprotect, which refers only to updates provided via iCloud, and doesn’t explain how those delivered via the traditional mechanism in softwareupdate might be involved. Yet we know there is a relation: the latest update has still not been supplied via iCloud, not even four days later, but relied instead on XProtectUpdateService working with an update obtained via softwareupdate. Previously that could be invoked using the xprotect update command, but that no longer works, leaving users with two versions of XProtect data, of which the copy used by XProtect and XPR is the older.
Late last year, when xprotect update appeared to be working as expected, I decided that my app SilentKnight would need to use that command in order to download and install updates. As that requires elevated privileges, I have been looking at how to implement a privileged helper app to perform that. With the latest update, that approach would have failed until the version in iCloud had been brought up to date. Instead we’re now reduced to restarting our Macs and hoping that, some time in the next day or two, they might update.
There’s a further problem emerging with the updates of 4 March. Many users have noticed subsequent XPR scans being terminated before completion. Although in most cases that fault appears to go away in later scans, in some Macs it prematurely terminates every set of XPR scans, leaving several of its scanning modules unused.
For example, this iMac Pro has failed to scan using ten of its 24 modules. This occurs because XPR apparently runs a timer, and when a round of scans is deemed to be taking too long, that timer fires and brings XPR to an abrupt halt. Indications are this is most likely when there are many Time Machine backups accessible; as those are all immutable snapshots and haven’t changed since they were made months ago, this is strange behaviour, and hadn’t occurred prior to the updates of 4 March.
Six months ago, if anyone had told me that macOS security protection in Sequoia was going to become less reliable, I wouldn’t have believed them. The truth is that, for many, it now has. As things stand in 15.3.1, a Mac is now more likely to be using an out of date version of XProtect’s detection rules, and for XPR scans to detect and remove malware. And there’s nothing you can do about that until Apple returns to using an update mechanism that’s both timely and reliable. Is that really too much to expect of this front-line security protection?
As those running macOS 15 Sequoia are only too painfully aware, the way that XProtect’s data is updated has changed from that still used in older versions of macOS. Instead of accessing that data in XProtect.bundle in the path /Library/Apple/System/Library/CoreServices, in Sequoia the data used is in /private/var/protected/xprotect. While the old location can still be updated using Software Update, SilentKnight and softwareupdate, the only way to update the copy in the new location is using the xprotect command tool, which normally obtains its updates through a connection to iCloud.
Updating in Sequoia
Since Sequoia 15.0, there has been a way to update data in the new location from XProtect.bundle in the old location, using the command sudo xprotect update
If that finds a newer version of the bundle in the old location, it installs its contents in the new location, so updating XProtect in Sequoia. At least, it did until the release of Sequoia 15.3 or 15.3.1.
When Apple released XProtect version 5288 on 26 February, it did so through both connections, and all versions of macOS were able to update promptly and successfully. That didn’t work with its successor 5289 on 4 March, though. Although the Software Update version was successfully updated in the old location to 5289, no iCloud update was made available, and sudo xprotect update proved unable to update from that to the new location.
This has left those running Sequoia 15.3.1 with version 5289 in the old location, but 5288 stuck in the new location. As Apple doesn’t tell us of these updates, nor of how XProtect is supposed to work in Sequoia or earlier, it’s impossible to tell whether this is intended, or an unintended failure.
Which rules does XProtect now use?
One potential explanation is that XProtect has returned to using its old location for the Yara rules, in /Library/Apple/System/Library/CoreServices/ XProtect.bundle/Contents/Resources/XProtect.yara. That’s fairly easy to check in the log, where it states the location of the rules it’s using to check an app for malware. The answer is com.apple.xprotect Using XProtect rules location: /var/protected/xprotect/XProtect.bundle/Contents/Resources/XProtect.yara
that’s the new location for Sequoia, and hasn’t changed since 15.0.
How does macOS now update the correct rules?
By chance, a few minutes after I had started my Mac mini M4 Pro yesterday, I opened SilentKnight and discovered that XProtect had successfully been updated to version 5289, something it wouldn’t do the previous evening following its release. At that time:
XProtect in its old location had been updated to 5289 the previous evening.
SilentKnight now reported XProtect in its new location was 5289.
sudo xprotect check reported the version in iCloud was still 5288.
sudo xprotect update reported that it was already up to date.
xprotect version reported that 5289 had just been installed, about 2.5 minutes after starting up.
This was an ideal opportunity to discover how XProtect had updated this time, by looking in the log with LogUI. That showed the update had been dispatched as a background activity by DAS, with ID com.apple.security.syspolicy.xprotect-update. That’s a scheduled background activity run every 24 hours, and in this case appears to have been dispatched because of the recent boot.
That activity connects to XProtectUpdateService, which then runs the check and updates as necessary, connecting to iCloud using CloudKit. On this occasion it ‘found’ the 5289 update, although maybe in its old location rather than in iCloud, and updated XProtect’s data in its new location.
How to keep XProtect up to date
From this experience, bearing in mind that everything might change again in the future, my advice is to:
Check for updates as usual using SilentKnight, Software Update, or softwareupdate.
When offered an update by any of those, install it gratefully.
Run SilentKnight a few minutes later. If that update isn’t reflected in the version shown, restart your Mac and leave it for 10 minutes or so before checking again.
If it still doesn’t update correctly, check again in about 24 hours, by which time DAS should have dispatched com.apple.security.syspolicy.xprotect-update with any luck.
Apple has just released updates to XProtect for all supported versions of macOS, bringing it to version 5289, and to XProtect Remediator for all macOS from Catalina onwards, to version 151. As usual, Apple doesn’t release information about what security issues these updates might add or change.
Yara definitions in this version of XProtect add two new rules for MACOS.TAILGATOR.RST.CT and MACOS.TEPIDTEA.
XProtect Remediator doesn’t change the list of scanner modules.
There is a new Bastion rule 13 for the behavioural version of XProtect (Ventura and later). This watches for execution of PasswordManagerBrowserExtensionHelper in CoreServices, in the App Cryptex, and makes an immediate report with the Signature Name of macOS.PasswordExtension.Exec if that occurs.
You can check whether these updates have been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install these as named updates in SilentKnight, their labels are XProtectPayloads_10_15-151 and XProtectPlistConfigData_10_15-5289.
Sequoia systems only
This update hasn’t yet been released for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check then enter your admin password. If that returns version 5289 but your Mac still reports an older version is installed, you can force the update using sudo xprotect update
This version is currently only available via Software Update, softwareupdate, or in SilentKnight, and not via iCloud. If your Mac is running Sequoia and you download it that way, the xprotect update command might take a while to use that downloaded version to update your Mac properly. As a result, the version of XProtect shown may remain at 5288, but should later change to 5299.
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Updated 1720 GMT 5 March 2025 following a ‘spontaneous’ update at 1631, although sudo xprotect check is still reporting the old version.
Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5288. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version adds two new rules for MACOS.TAILGATOR.UPD and MACOS.TAILGATOR.INLASCLDR.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5288.
Sequoia systems only
This update is also available for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then entering your admin password. If that returns version 5288 but your Mac still has an older version installed, you can force the update using sudo xprotect update
This version is now available via Software Update, softwareupdate, or in SilentKnight as well. If your Mac is running Sequoia and you download it that way, rather than using iCloud, then once it’s installed you’ll need to run the update command for that to take correctly.
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5287. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version adds two new rules for MACOS.FLUFFYFERRET.CT and MACOS.TAILGATOR, together with a complete set of UUIDs for all existing rules.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5287.
Sequoia systems only
This update is now also available for Sequoia via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then entering your admin password. If that returns version 5287 but your Mac still has an older version installed, you can force the update using sudo xprotect update
This version is now available via Software Update, softwareupdate, or in SilentKnight as well. If your Mac is running Sequoia and you download it that way, rather than using iCloud, then once it’s installed you’ll need to run the update command for that to take correctly.
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Updated 2240 GMT 5 February 2025 with iCloud release.
Many of the background activities managed by Duet Activity Scheduler and Centralised Task Scheduling, the DAS-CTS system, are largely invisible to the user, as they’re services supporting other services. Two of the best-known activities are automatic Time Machine backups and XProtect Remediator scans for malware. I first came to learn about DAS-CTS eight years ago when investigating problems with backups in macOS Sierra, and have written extensively here about how they work. This article concentrates instead on XProtect Remediator scans, which are more recent and an important part of security defence in macOS.
XProtect Remediator (XPR) appears, and to a degree can work, like an app, located in /Library/Apple/System/Library/CoreServices/XProtect.app. Look inside its bundle and in the MacOS folder you’ll see its code alongside 24 scanning modules. These are run through LaunchAgents and LaunchDaemons property lists in its Resources folder. Once a day XPR runs a paired set of scans to detect and remove or remediate known malicious software. These are scheduled and dispatched by the DAS-CTS system, and understanding how they work helps diagnose and address problems that can arise with XPR scans.
Launch Events
XPR contains two key property lists setting up its scans, com.apple.XProtect.agent.scan.plist and com.apple.XProtect.daemon.scan.plist. These are essentially the same, the first to run scans as the current user, and the second as root. They define three types of Launch Events, which for the user are:
a fast scan, com.apple.XProtect.PluginService.agent.fast.scan, performed at intervals of 6 hours (21600 seconds), and run when on battery;
a standard scan, com.apple.XProtect.PluginService.agent.scan, performed at intervals of 24 hours (86400 seconds), but not run when on battery;
a slow scan, com.apple.XProtect.PluginService.agent.slow.scan, performed at intervals of 7 days (604800 seconds), but not run when on battery.
These are assigned a ProcessType of Background, so are scheduled and dispatched by the DAS-CTS system.
What the scans do
In the standard scan, each of the scanning modules is run in turn, once using the agent version running as the current user, normally 501, and once using the daemon version as root, user 0.
You’re unlikely to see any evidence of a fast scan at the moment, although they should be run every 6 hours. Fast scans only run specific scan modules designated by Apple as meriting such frequent checks. This was used during a period of high threat soon after XPR was first introduced, but as far as I’m aware hasn’t been used since. Currently, when a fast scan is run, each scanning module in turn is reported as not being required to run, and those single-line entries are the only records left in the log. That could of course change in response to a change in threat.
As a slow scan is only run once a week, they’re hard to locate in the log. So far I haven’t discovered any.
The results from standard scans are thus the only XPR activities you’re likely to see in the logs, and using XProCheck.
You can read relevant log entries using the DAS Scheduling log extract feature in Mints, or a generic log browser like Ulbow using the filter predicate subsystem == "com.apple.duetactivityscheduler" OR subsystem CONTAINS "com.apple.xpc"
Registration
During startup, XPR’s property lists are read and its activities are registered by DAS-CTS. For example, this series of log entries reports the LaunchAgent for standard scans being registered following user login:
CTS Creating on XPC add event: com.apple.XProtect.PluginService.agent.scan
CTS Created: com.apple.XProtect.PluginService.agent.scan (0x9cc8652c0)
DAS Submit activity: <private> in group: <private> with capacity: 1
CTS Submitting: 501:com.apple.XProtect.PluginService.agent.scan:0B9197 (CTS Activity 0x9cc8652c0)
DAS SUBMITTING: 501:com.apple.XProtect.PluginService.agent.scan:0B9197
CTS Registered: com.apple.XProtect.PluginService.agent.scan (0x9cc8652c0)
DAS Submitted: 501:com.apple.XProtect.PluginService.agent.scan:0B9197 at priority 30 with interval 86400 (Sun Jan 26 23:23:56 2025 - Mon Jan 27 23:23:56 2025)
Its priority setting is different from the Quality of Service (QoS) set in its property lists, which is Utility, matching a QoS raw number of 17, not 30. That’s common, and demonstrates how QoS values set in the API aren’t the same as those used internally in macOS.
At this stage, DAS makes its first assessment as to whether to dispatch this activity. As this occurs within five minutes of starting up, DAS decides it Must Not Proceed, MNP. The Optimal Score for that activity is reported, and set as the minimum score it must achieve before DAS will dispatch it to be run.
DAS 501:com.apple.XProtect.PluginService.agent.scan:0B9197:[
{name: Boot Time Policy, policyWeight: 0.010, response: {33, 0.00, [{[Minimum seconds after boot]: Required:300.00, Observed:39.00},]}}
{name: Device Activity Policy, policyWeight: 20.000, response: {33, 0.00, [{deviceActivity == 1}]}}
], Decision: MNP}
DAS <private>: Optimal Score 0.6872 at <private> (Valid Until: <private>)
Dispatch
DAS rescores activities in its list at frequent intervals. When an XPR activity, here the LaunchDaemon version of XPR’s standard scan, exceeds the threshold, DAS makes the decision that the activity Can Proceed, CP.
DAS 0:com.apple.XProtect.PluginService.daemon.scan:847936:[ ], Decision: CP Score: 0.980125}
DAS '0:com.apple.XProtect.PluginService.daemon.scan:847936' CurrentScore: 0.980125, ThresholdScore: 0.587700 DecisionToRun:1
DAS With <private> ...Tasks pre-running in group [com.apple.dasd.default] are 1!
DAS 501:com.apple.XProtect.PluginService.agent.scan:0B9197:[ ], Decision: CP Score: 0.980125}
Some activities, presumably those identified as CPUIntensive or DiskIntensive in their property lists, are then checked against others for compatibility. This is marked by a sequence of those checks, such as
DuetAS '501:com.apple.XProtect.PluginService.agent.scan:0B9197' has compatibility score of -1.000000 with 0:com.apple.XProtect.PluginService.daemon.scan:847936 (Started at <Not yet started>). Bailing out.
In this case, it ensures that user and root scans aren’t run at the same time.
Once DAS is happy that starting this scan is desirable and compatible, it then requests CTS to start the activity.
DAS REQUESTING START: 0:com.apple.XProtect.PluginService.daemon.scan:847936
CTS DAS told us to run com.apple.XProtect.PluginService.daemon.scan (0x61e2fc140)
CTS evaluating activities
CTS com.apple.XProtect.PluginService.daemon.scan state change 1 -> 2
CTS Initiating: com.apple.XProtect.PluginService.daemon.scan (0x61e2fc140)
CTS _xpc_activity_dispatch: beginning dispatch, activity name com.apple.XProtect.PluginService.daemon.scan, seqno 0
CTS _xpc_activity_dispatch: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0): found an activity with matching seqno 0
CTS _xpc_activity_begin_running: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0) seqno: 0.
CTS _xpc_activity_dispatch: lower half, activity name com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), seqno from top half was 0
CTS _xpc_activity_dispatch: created connection 0x123004ac0 for activity name com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), seqno 0
CTS _xpc_activity_set_state: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), 2
CTS _xpc_activity_set_state: send new state to CTS: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), 2
CTS Running (PID 2351): com.apple.XProtect.PluginService.daemon.scan (0x61e2fc140)
DAS STARTING: <private>
CTS _xpc_activity_set_state_from_cts: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), set activity state to 2
CTS XPC_ACTIVITY_CALLING_HANDLER__: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), current state 2, pending state 0
CTS _xpc_activity_set_state: com.apple.XProtect.PluginService.daemon.scan (0x6000035200a0), 4
DAS then records that the activity started:
DAS STARTING <_DASActivity: "0:com.apple.XProtect.PluginService.daemon.scan:847936", Utility, 60s, [26/01/2025, 23:23:54 - 27/01/2025, 23:23:54], Started at 27/01/2025, 12:05:36, Group: com.apple.dasd.default, Intensive: CPU Disk, PID: 2351>!
DAS Activity <private> has preventDeviceSleep 0. PluggedIn state: 1
DAS With <private> ...Tasks running in group [com.apple.dasd.default] are 3!
DAS Started <private>, total runtime from previous runs 0.0 mins
DAS 0:com.apple.XProtect.PluginService.daemon.scan:847936:[ ], Decision: CP Score: 0.980125}
Diagnosis
The only common problem encountered in running XPR is an apparent failure to run daily scans. Relevant causes are:
Insufficient log records, that don’t cover sufficient time to capture a set of scans.
Running a notebook on battery, as standard scans won’t be dispatched unless the Mac is running on mains power.
Running other CPU- or disk-intensive tasks, which may cause scans to be deferred until those are completed.
High thermal load, which will cause scans to be deferred until thermal conditions have improved. This is the origin of Duet in Duet Activity Scheduler, referring to the CoreDuet system responsible for monitoring the Mac’s operating environment and managing tasks appropriately.
Failure of DAS to score activities in its list, currently extremely improbable, but can only be diagnosed from its log entries.
Other failures in DAS-CTS, which again require log analysis.
One of the difficulties in diagnosis is that there’s no command tool that can inspect DAS activity lists, making log inspection essential in most cases.
For many who prefer to wait a little, the x.3 update is a popular time to upgrade to the next major version of macOS. By then, most of the major bugs should have been fixed, and some fine tuning performed on new features. So if you’ve just joined Sequoia from something older, you might now be wondering what on earth is going on with XProtect, which still baffles those of us who have been here since 15.0.
Which XProtect?
First allow me to dispel a common confusion: this article is about the XProtect we know of old, run on demand during Gatekeeper checks before macOS launches code. This isn’t the same as XProtect Remediator (XPR), a suite of scanning modules, that periodically searches your Mac to detect and remove known malware. Unlike XPR, XProtect leaves little trace in the logs, merely that it has checked code for malware and didn’t find any.
XProtect relies on a handful of configuration files in a bundle that doesn’t itself contain any code. Most important among them is a file containing a large and growing set of rules used to detect malicious code, the Yara rules. Every two weeks, Apple’s security engineers assemble the latest set of Yara rules into the bundle named XProtect.bundle and it’s distributed as an update from Apple’s servers.
Whichever earlier version of macOS your Mac has been running, it has downloaded those updates using Software Update, SilentKnight or a similar mechanism, installed that bundle into /Library/Apple/System/Library/CoreServices, and the next time that XProtect is run on demand it uses those updated rules to improve your Mac’s protection against malware.
Changes in Sequoia
In the past, XProtect has been something of a quiet backwater, and its Yara rules changed little and infrequently. That has changed dramatically over the last couple of years, and the rules have grown in number, size and sophistication. They have also become more responsive, to ensure XProtect’s checks keep up with the latest malware and its changes.
For Sequoia, Apple has changed the way that XProtect is updated, and where its Yara rules and other files are kept, to /var/protected/xprotect/XProtect.bundle, although previous versions of macOS continue to receive their updates as before. Updates for Sequoia can be delivered either via a connection to iCloud, or the established method to Apple’s Software Update servers.
Last week’s updates
Last week, the regular fortnightly update to XProtect 5286 was ready for release on 27 January, but macOS Sequoia 15.3, security updates, and updates to all the other OSes were released instead. They put a heavy load on the Software Update servers, so it appears the update to XProtect 5286 was delayed. That was a wise decision: Apple has previously tried releasing security data updates at the same time as OS updates, and it doesn’t work out well for anyone.
In the early hours (GMT) of 29 January, XProtect 5286 was released for download to macOS Sequoia via its iCloud connection. As this doesn’t use the servers responsible for macOS and other OS updates, that took advantage of this new feature in Sequoia. Most of the Macs running 15.0 or later were most probably updated to 5286 by the end of that day.
Twenty-four hours later, in the early hours (GMT) of 30 January, the same updated version of XProtect was released for download from Apple’s Software Update servers, enabling those still running older versions of macOS to install the update, as the load must have been reducing on those servers.
Although that seems clear and straightforward, what users saw often appeared puzzling if not incorrect. If you were running Sequoia, your XProtect data bundle with its Yara rules was probably updated silently during 29 January, but the following day (when your Mac was already enjoying the protection of the update) you were offered the 5286 update by Software Update, softwareupdate or SilentKnight, as if your Mac still had’t been updated. Some of you thought that was the real update, but it wasn’t, as that only updated the bundle stored at the old location, which isn’t used by XProtect in Sequoia.
How it worked
For the great majority of folk who don’t even know what XProtect is or does, this is all irrelevant, as their Macs continue to work as before, just improve their malware detection silently. For those of us who take an interest, or want to know what’s going on, it can appear profoundly confusing. To help clarify, here are two different ways that a Mac running Sequoia could successfully install XProtect 5286.
The preferred way is using the new iCloud connection, which doesn’t require that you have connected to iCloud, as it’s made outside your Apple Account or iCloud Drive. To start with, both copies of the XProtect bundle are version 5285. Then, probably on 29 January, that Mac connects to iCloud and downloads the update direct to its new location (red). Although the copy in the old location remains at version 5285, the copy used by XProtect is now using the updated rules in 5286.
Then, when the Software Update copy is installed the following day, both copies are brought up to 5286.
But Sequoia can still make use of the general release of the new version, as shown in this second diagram. Suppose that Mac running Sequoia didn’t have access to iCloud on 29 January, and the following day isn’t able to update to 5286 via iCloud. However, that update is still delivered from the Software Update servers. Over the next minutes or hours, macOS can then use that copy of the XProtect bundle to update the bundle now used by XProtect in Sequoia, as shown on the bottom line. If that doesn’t work, the user can run sudo xprotect update
in Terminal, and that will force the local update.
Improvements
The benefits of this new system to the Sequoia user are therefore:
updating 24 hours earlier, when Software Update servers were still heavily loaded;
fall back to the traditional method if an iCloud update doesn’t occur, followed by local installation to the new location.
Now we can all return to trying out Genmoji. While they may be trivial by comparison, they bring a lot of fun to Messages, and we could all do with plenty of fun as well as better security.
Apple has overnight released an update to XProtect for all supported versions of macOS, bringing it to version 5286. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version removes the rule for MACOS.1afcb8b, and adds three new rules for MACOS.FROSTYFERRET.UI, MULTI.FROSTYFERRET.CMDCODES and MACOS.FRIENDLYFERRET.SECD. It seems the animal of the week is a ferret.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight, LockRattler and SystHist for El Capitan to Sequoia available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight, LockRattler, or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5286.
Sequoia systems only
This update is also available for Sequoia only via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then entering your admin password. If that returns version 5286 but your Mac still has an older version installed, you can force the update using sudo xprotect update
This version is now available via Software Update, softwareupdate, or in SilentKnight as well. If your Mac is running Sequoia and you download it that way, rather than using iCloud, then once it’s installed you’ll need to run the update command for that to take correctly.
I have updated the reference pages here which are accessed directly from LockRattler 4.2 and later using its Check blog button.
Early today Apple released an update to XProtect for macOS Sequoia only bringing it to version 5286. As usual, Apple doesn’t release information about what security issues this update might add or change. Macs running earlier versions of macOS should still be using version 5285.
This version removes the rule for MACOS.1afcb8b, and adds three new rules for MACOS.FROSTYFERRET.UI, MULTI.FROSTYFERRET.CMDCODES and MACOS.FRIENDLYFERRET.SECD. It seems the animal of the week is a ferret.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
This update is now available for Sequoia only via iCloud. If you want to check that manually, use the Terminal command sudo xprotect check
then entering your admin password. If that returns version 5286 but your Mac still has an older version installed, you can force the update using sudo xprotect update
Currently, this new version isn’t available via Software Update, softwareupdate, or in SilentKnight, and is only available via iCloud connections to Macs running Sequoia.
Several of my most popular apps make use of the main system log in macOS, and I occasionally get questions from those who can’t get them to work properly because their Mac’s log files have mysteriously disappeared. This has puzzled me for the last few years, but I think I’ve discovered the cause: some apps delete those log files in a misguided attempt to clean up your Mac and save storage space. This article explains why you shouldn’t do that.
Which logs?
In theory, since macOS Sierra introduced the macOS Unified log, there should be only one log, and one folder containing its log files, hidden away in /var/db/diagnostics.
In practice, many apps and even parts of macOS ignore those and write their own log files. Those can appear almost anywhere, but popular locations include:
~/Library/Logs, the worst offender;
/Library/Logs, which should be better maintained;
/var/log, normally properly maintained;
/var/logs, small and properly maintained.
Those locations contain a mixture of ephemeral information of little value, and some potentially important records, such as the outcome of all volume checks made by fsck on APFS and HFS+ volumes. If your Mac was migrated from a previous model, that may well have copied across logs going back years, and those four folders could well contain dozens of files, and consume several GB of space on your Mac’s startup disk.
What maintains them?
While the Unified log has a dedicated service, logd, that is constantly maintaining the files in /var/db/diagnostics, there’s no app or service that maintains all the others. As they’re considered to be custom features outside the control of the main log, it’s up to the apps that write them to remove old entries when they’re no longer required. Routine system housekeeping used to be performed at regular intervals, run by periodic scripts, but even those have been removed from macOS Sequoia, and before that much of the responsibility still rested with apps that create their own logs.
Logs in /var/log and /var/logs should be well maintained, but for most of logs written outside the Unified log, the answer is that apps responsible for maintaining their own logs don’t, and leave it to the user to clean up after them. Neither do those apps warn the user that they write their own logs but don’t maintain them.
Unified log
Look down through the list of active processes in Activity Monitor and you’ll see two, logd and logd_helper, that are always present from shortly after a Mac starts up until it shuts down. Unlike traditional Unix logs, the Unified log is maintained so its size remains fairly constant, with the main folder of log files, Persist, taking up a little more than 500 MB, and the whole of /var/db/diagnostics coming to about 1.5 GB.
logd does this by working through all the individual entries in the log files and removing those that have passed their retention time. It thus preserves more important entries for longer, and prevents the logs from growing uncontrollably. The unfortunate side-effect of this is that Macs that are making copious log entries have logs that don’t go back long in time. At its worst, that might mean that they may only last a few hours before logd removes them.
Although the Console app provides limited features for accessing your Mac’s log, and the great majority don’t want to go near it, the Unified log has important contents. Among those are reports by Time Machine on its recent backups, and those from XProtect Remediator on its scans to detect and remove malware. It’s also the place where all significant errors and failures should be recorded. Remove the main log files and those all disappear. Apple also may ask for and use recent log records when investigating problems you report to Apple Support or, for developers, using Feedback. Even though you may not want to browse the log yourself, it’s important and not a feature you should throw away.
Housekeeping
Spending a little time every month or so doing the housekeeping on your Mac is an excellent and rewarding investment of your time. When I do this, I like to preserve those logs that might still be significant, including the inevitably copious files written by Adobe’s multitude of services, and anything that still appears to be active. But those that haven’t been modified for the last year or so should be disposable, and any from apps I no longer use can be cleared away without fear. However, I never interfere with the Unified log in /var/db/diagnostics as I know that logd cares for that constantly, and much better than I can.
I’m well aware that many feel that they can delegate the responsibility of housekeeping to an app, now typically one they pay a substantial subscription for. Just as I wouldn’t pay someone to come and work through all my personal papers and records, destroying those that they thought I didn’t need, I will never use an app that does the same with my Macs. If the housekeeping app you use deletes log files, particularly if those could include those of the Unified log, then I’d consider that to be malicious, and proof that the app’s developers don’t understand how macOS works.
And that’s why some discover that those vital logs have been destroyed, and they can’t run the checks built into several of my apps, including the records of XProtect Remediator’s security scans.
Recommendations
Users: perform housekeeping as a routine, particularly on disused and unnecessary logs in ~/Library/Logs. Never interfere with logs stored in /var/db/diagnostics.
Developers: avoid writing your own logs. If your software really has to, ensure that it performs its own housekeeping, and inform the user in its documentation.
Apple: if the Unified log can’t be unified, improve it and make it fit for purpose.
Many Mac notebooks lead a busy life. Although they might get a decent sleep, they’re seldom left idle when on mains power. This article looks at some of the tasks that can’t normally be run when a Mac is running on battery power, and may get left undone if it’s too busy when recharging.
Sparse bundles
The only user task among these might catch you by surprise. Sparse bundles (the disk images that store files inside a bundle folder rather than in a single file) may need to be compacted occasionally to ensure they don’t grow larger than they need. Because compaction can take a long time and can’t be interrupted without risking the whole sparse bundle’s contents, by default it won’t be performed when a Mac is running on battery power. That can be overridden in some utilities like my own Spundle, and in the hdiutil command.
Daemons and agents
Although I can’t find them documented anywhere, there are two keys used in the property lists used for LaunchDaemons and LaunchAgents that determine whether their activities and background services will be run when a Mac is running on battery power. AllowBattery is set to true when the service can be run on battery, or to false when it can’t. You will also come across the opposite, RequiresExternalPower, set to true when it can’t be run on battery, or to false when it can. Be careful interpreting their meaning.
Spotlight
Spotlight’s in-app service Core Spotlight consists of many services, some of which aren’t allowed when on battery. Those include:
com.apple.corespotlightd.updateContacts in corespotlightd, which presumably updates information for Contacts’ database;
several parts of com.apple.spotlightknowledged, which is concerned with ‘knowledge’ additions to Spotlight features. These include com.apple.corespotlight.knowledge and its subtasks for inference, journals, and updates;
two parts of com.apple.photoanalysisd, used to analyse media content, in two parts backgroundanalysis and (surprisingly!) music;
several debug services in com.apple.corespotlight.knowledge, which shouldn’t have any user impact.
XProtect Remediator
As we’ve recently realised, regular scans performed by XProtect Remediator (XPR) to detect and remove known malicious software can busy a whole E core for well over half an hour. Because of that, some of its services will only be run when a Mac is powered by mains (AC). There is a ‘fast scan’ that can still take place when on battery, but that doesn’t appear to work through the specialist scanning modules for known malware, and doesn’t record similar entries in the log.
You can observe this yourself after starting your Mac up for the day. If it’s running on mains power and left alone for 10-15 minutes, XPR will usually start scanning with each of its modules. However, if you start your Mac up on battery and leave it for a couple of hours, there’s no sign of those scans starting. This is the result of the AllowBattery key of both com.apple.XProtect.PluginService.agent.scan and com.apple.XProtect.PluginService.agent.slow.scan being set to false in XPR.
Consequences
Most of these services will normally run when a Mac is awake, but not in heavy use. If your Mac spends little time in that state with mains power connected, then they may not be run for many days. When they do get a chance, then you may see long periods during which these services take a significant % CPU in Activity Monitor. If you open its CPU History window on an Apple silicon Mac, you should see them running almost exclusively on the E cores. This ensures that they don’t affect what you’re doing, but they do need the time to do their work uninterrupted, when possible.
For XProtect Remediator, this means that its full scans to detect and remove malicious software won’t take place. While you can run them manually, for example using my free XProCheck, that only runs one set of the two that are normally performed when XPR is run automatically.
Lunch breaks
Many humans take a break at lunch, when they stop their normal work and engage in maintenance. Although some take the opportunity to catch up with their sleep, in most cases folk stay awake.
That’s a model that could allow your MacBook Pro or Air to catch up with some of these background tasks that it needs to have mains power for. Rather than closing its lid to force it to sleep, why not leave it open, awake, running without the load you normally impose on it, and catching up on its Spotlight services and, most important of all, running XProtect Remediator scans? That needn’t necessarily be every day, but a couple of lunch breaks each week could be beneficial for both of you.
I’m grateful to Michele for inspiring this from his own experience.