Reading view

There are new articles available, click to refresh the page.

What can I do with my apps?

One of the longstanding joys of the Mac has been how you can customise apps, giving them new icons and, in the past at least, even a few gentle tweaks. What’s unfortunate is that changing apps isn’t just for users. If we can alter them, so can an attacker, and the last thing any of us would want is for Safari or Preview to turn malicious. Over the years the scope for making changes to apps has therefore been reduced. This article explains how, and what we can still do.

To understand how customisation has been limited, we need to know what can and can’t change.

Signature

The most basic requirement of any app is that it’s signed. This provides a set of hashes that can be used to verify that none of its contents have been changed since that app was signed, and those hashes are hashed again to product code directory hashes, CDHashes, that are used to identify and recognise the app. Whatever we might customise in an app, its CDHashes must match its contents.

Certificate

Next comes the chain of trust established by the certificate used to sign the app. Developer certificates are issued by Apple as their Certificate Authority, so they each can be traced back through an Apple Intermediate certificate to Apple’s Root certificate, the chain of trust.

An Apple-issued certificate isn’t required for macOS to run an app, though. Because many Mac users build their own apps locally from open source, local or ad hoc certificates are also acceptable. However, anyone can sign an app with an ad hoc certificate, including an attacker, and, apart from the few malicious apps that have been signed using developer certificates, all other malware for the Mac is now ad hoc signed. As ad hoc signatures have no chain of trust, you can’t put any trust in them.

Notarization

Over the last few years, Apple has required developers to get their apps notarized. That involves ensuring the app meets certain security requirements, and is submitted to Apple to be checked to see if it contains any malicious code. Apps that satisfy those requirements are then issued with a ticket, that’s usually stapled inside the app’s bundle. That consists of the app’s set of CDHashes, again used to identify and recognise that app.

Although there’s no reason that you can’t notarize your own apps, and any you have resigned, that requires a paid-for subscription as a developer, putting it out of the reach of most. However, in an enterprise it can prove useful.

Launch constraints

Since macOS 13.3 Ventura, a new set of restrictions have been imposed on all apps and command tools provided as part of macOS, in launch constraints. These are rules that must be met for macOS to launch that app or binary, and include self constraints that the binary itself must meet, parent constraints that must be met by its parent process, and responsible constraints that must be met by the process requesting the launch.

Launch constraints for bundled apps prevent them from being run from anywhere else. If you manage to make a copy of any of those apps, and that’s a challenge in itself, then macOS will prevent you from running that copy. This is made harder to avoid by the fact that these launch constraints are stored in an inaccessible Trust Cache, so the only way you could work round those rules is by turning System Integrity Protection (SIP) off, which in turn reduces Boot Security. That’s explained in more detail here.

Although third-party apps don’t get to use launch constraints or the Trust Cache, some may now have started using environment constraints, which can have similarly restrictive effects. The best way to discover this is using Apparency, which also includes a full guide to the constraints available.

Bundled apps

If you can’t remember which apps are bundled and which are not, look in /System/Applications, as that shows all those in the Signed System Volume, to which you need to add Safari, as that’s sealed in a cryptex.

Sadly, because of all their levels of protection, you can’t customise any of the bundled apps. Even copying them from their read-only SIP-protected location to a folder in your Home folder, which is difficult enough, that copy can’t be run, no matter what you do to it. You can make a Finder alias to the original app and give that a custom icon that will appear in Finder windows. But the app’s original icon will still be displayed everywhere else, including in the Dock, so it’s simply not worth the effort.

If you had ideas that you could replace all Tahoe’s new-style app icons with those from Sequoia, I’m afraid you will be disappointed.

Third-party apps

One customisation you can apply in complete safety is to replace a regular app’s icon. To do that, paste the new icon into the top left of its Get Info dialog, and further information is given here. This doesn’t affect any of the security protection of that app, as the new icon is added as a hidden Icon file at the top level inside the app’s bundle, which isn’t included in its CDHashes.

Any more substantial changes, even to the app’s resources, should break its signature and CDHashes, and macOS won’t like that.

If there’s a really good reason for making a change, and you can justify resigning the app using an insecure ad hoc signature, you could try stripping its current signature, changing the app bundle, then resigning it with an ad hoc signature. There are two cautions, though:

  • Any ad hoc signature is inherently insecure, and makes it simple for malicious code to tamper with that app.
  • This may break the app’s updating process, and if it doesn’t, any update will undo your customisation.

Before going any further, you’ll need to add Terminal to the list in System Settings > Privacy & Security > App Management, otherwise your commands will be unable to make any changes to the app. Then make a copy of the app you intend to change, so you can readily revert to the original. Once you’ve done that, open Terminal and use the command
codesign --remove-signature MyApp.app
to strip the existing signature from the app MyApp.app. Note that two hyphens precede the remove-signature verb.
When you’ve made your changes, use the command
codesign --sign - MyApp.app
to sign that app with an ad hoc signature.

Summary

  • Apps bundled in macOS from 13.3 onwards can’t be copied and run from elsewhere, preventing all customisation, and can’t be given custom icons.
  • Third-party apps can have custom icons applied in the normal way.
  • Any internal surgery inside the app bundle will break its notarization and signature, and shouldn’t be attempted.
  • If it’s an essential change, you may be able to strip the signature, make the change, and resign with an ad hoc signature.
  • Ad hoc signatures are inherently insecure, and should be avoided if at all possible.

Is Tahoe quicker to launch apps first time?

One of the longstanding oddities in macOS security has been scanning of a notarized app by XProtect before it can be launched. When apps are submitted to Apple for notarization, they’re scanned for malicious content using methods at least as effective as XProtect, and should any notarized software subsequently be identified as malicious, its notarization and signature are revoked immediately. That should make it impossible for any app with a valid notarization ticket to contain malware known to Apple.

One of the improvements believed to be incorporated into macOS 26 Tahoe is that validly notarized apps are no longer scanned by XProtect. When I examined this recently, I confirmed that was correct, although in practice this did little if anything to improve the launch times of apps. This article extends those observations to include app first run, when detection of malware is most critical.

When an app is run for the first time in a recent version of macOS, there are three options:

  • apps that aren’t quarantined, including those signed by Apple and almost all of those supplied through the App Store, normally don’t undergo additional checks;
  • quarantined apps that have been installed correctly undergo full first run checks, that have previously included XProtect scans;
  • quarantined apps being run from the immediate location they arrived in not only undergo full first run checks, but are additionally moved to be run from a random path in what’s commonly known as app translocation, or Gatekeeper Path Randomisation (GPR).

This article considers the second and third of those.

Quarantined first run, no translocation

In Sequoia 15.7 these apps undergo a “direct malware and dylib scan” using the XProtect data stored in its new location, in /var/protected/xprotect/XProtect.bundle. Because this is the first run, once Gatekeeper assessment is complete and confirms the app is safe to run, the user is presented with a dialog asking for their consent. Because of the inevitable delay in responding to that, two times can provide meaningful estimates of performance:

  • the time between the log entry reporting that Gatekeeper is performing a scan (“GK performScan”), and declaring the Gatekeeper scan complete (“GK scan complete”), in this case 5.35 seconds;
  • the time between the start of the XProtect scan (“Xprotect is performing a direct malware and dylib scan”) and the declaration of scan results (“GK Xprotect results”), here 5.33 seconds.

In Tahoe 26.0 no XProtect scan was attempted, as com.apple.xprotect entered in the log “Xprotect is skipping executable assessment”, and com.apple.syspolicy.exec confirmed “Skipping XProtect scan on seen software”. Despite that, the first of those times was nearly twice that required in Sequoia, at 10.29 seconds. The reason for this is unknown, but over that period the log contained about 13,000 entries reporting “SecKeyVerifySignature”.

As a result, a smaller and simpler app was used to test app translocation and its effects.

Quarantined first run, with app translocation

Instead of using Calibre as my test app here, I chose my own app Podofyllin, with its 442 KB executable and no dylibs or other complications. This was downloaded from here, unarchived automatically in the ~/Downloads folder and there run from the folder it came in, to ensure that it would be translocated.

Early in the launch sequence, com.apple.securityd writes a log entry indicating it has created the translocation directory “SecTranslocateCreateSecureDirectoryForURL”, following which diskarbitrationd replicates the app bundle to what appears as a different volume in the translocation path. Then a first run Gatekeeper assessment is performed, including an XProtect scan, checking the notarization ticket using CloudKit, a user approval dialogue, and setting up the app’s provenance tracking.

In Sequoia 15.7, the XProtect scan took 0.15 seconds, and the total period required for the Gatekeeper scan was 0.19 seconds.

In Tahoe 26.0, com.apple.syspolicy.exec logged “Skipping up front XProtect scan” and com.apple.syspolicy went straight on to perform the CloudKit lookup. This was confirmed later by com.apple.syspolicy.exec in “Skipping XProtect scan on seen software” just before reporting the Gatekeeper scan was complete. With no time required for the XProtect scan, the total used for the Gatekeeper scan was 0.16 seconds, 88% of that for Sequoia.

Stuck in translocation

Over the last couple of years it has become clear that some apps, even though they have been moved from their original download location, continue to undergo translocation whenever they’re run, and that can cause ongoing problems.

An app will be translocated if all the following apply:

  1. the app has a com.apple.quarantine extended attribute attached;
  2. the app must be opened by Launch Services (normally the Finder) rather than a command shell;
  3. the app hasn’t been individually moved in the Finder from the folder it was unarchived or downloaded to, wherever that was.

Tests in recent macOS show that apps won’t be translocated if:

  • they have no com.apple.quarantine extended attribute, or it has been removed;
  • they have been moved individually in the Finder so they’re now enclosed in a different folder.

The following will normally result in the app being run in translocation:

  • opening the app in the folder that it first arrived in, even if that folder has been moved elsewhere, such as into an Applications folder;
  • moving the app at the same time as other apps, even if they’re all put into an Applications folder. Group or simultaneous moves in the Finder aren’t counted as a move that will stop future translocation;
  • running the app again without moving it from a location from which it has already been translocated. Until the app is moved from that location, it’s likely to be repeatedly translocated every time that it’s run.

You can readily check whether an app is being run in translocation by starting the app and either:

  • inspecting that app in Activity Monitor, by selecting it in the CPU view and clicking on the ⓘ tool,
  • running ps xw | grep AppName in Terminal.

If the path shown for the app is something absurdly long like /private/var/folders/x4/[random chars]/T/AppTranslocation/[UUID]/d/, then it has been translocated.

If an app that appears to have been correctly installed is still being translocated, move it individually (one app at a time) from the folder it’s currently in to a different folder, run it from there, close the app, and move it back to where you want to keep it.

Conclusions

  • macOS 26.0 Tahoe skips reported XProtect malware scans when a notarized app is run for the first time in quarantine, even when it has been translocated.
  • Despite that, first run checks in Tahoe can still take significantly longer than in subsequent runs, although the reason for that isn’t clear from the log.
  • If an app doesn’t appear to run properly, check whether it’s stuck in translocation. If so, free it as explained above.

Do apps launch faster in macOS Tahoe?

One seemingly widespread complaint about recent versions of macOS has been slow launch times of notarized apps even after they have cleared quarantine in their first run. Debate on the cause of this was vigorous in April and May, but was overtaken by Apple’s announcement of macOS 26 Tahoe. I therefore postponed further work on app launch and Gatekeeper until after Tahoe’s release.

This proved worthwhile, as soon after the first beta-release, it was suggested that Tahoe would accelerate the first launch of notarized apps by exempting them from a malware scan, although I have been unable to confirm that from Apple’s published information. That would make good sense: if an app’s CDHashes verify and match those of its notarization ticket, and no known malware was found when it was notarized, then it’s not plausible for it to contain malicious content since notarization was performed. This article considers what has changed in Gatekeeper in macOS 26.0.

Although Apple hasn’t yet updated it for macOS 26, its Platform Security Guide explains what Gatekeeper does in macOS Sequoia. For an app, plug-in or an installer package downloaded from outside the App Store and opened on a Mac, Gatekeeper verifies the software:

  • is from an identified developer, in signature checks;
  • is notarised by Apple to be free of known malicious content, in notarization ticket checks;
  • hasn’t been altered, in CDHash verification;
  • doesn’t contain known malicious content the first time it’s opened, regardless of how it arrived on the Mac, in a first run XProtect scan.

To assess this, I have used Calibre version 8.11.0 installed in a macOS virtual machine running on a Mac mini M4 Pro. Calibre is a large app at just over 1 GB with many components to be checked. This version has 82 items in its Frameworks folder, 20 executables in its MacOS folder, and 25 dylibs in its Plugins folder, totalling 113 dylibs and others that need to be checked.

Two VMs were prepared, one with macOS 15.7 Sequoia installed, the other with macOS 26.0 Tahoe. Both were run with 5 CPU cores, 16 GB memory, 100 GB disk, and bridged networking.

Calibre was launched three times in Tahoe, first when freshly installed and still in quarantine. Following that, the VM was shut down, started up 4 hours later and Calibre was run a second time. The VM was shut down again, and started up two days later for a third run. Log extracts were collected within a minute using LogUI.

Tahoe: First run in quarantine

This proceeded similarly to first run in Sequoia, with the exception of XProtect malware scanning. Soon after com.apple.syspolicy.exec reported that a GK (Gatekeeper) process assessment was starting, it wrote the log entry
Skipping up front XProtect scan on: PST: (path: f0970f7f0ab1ff9f), (team: NTY7FVCEKP), (id: (null)), (bundle_id: (null))
That was reiterated later, shortly before the outcome of the GK evaluation
Skipping XProtect scan on seen software: PST: (path: f0970f7f0ab1ff9f), (team: NTY7FVCEKP), (id: (null)), (bundle_id: (null))
There were no other log entries that suggested an XProtect malware scan had been attempted.

As is normal in the first run, notarization was checked using CloudKit, there was abundant evidence of CDHash verification, the user was prompted for their approval, and once that was complete the code was allowed to proceed.

Despite the lack of an XProtect scan, launch was as long as previous first runs in recent versions of macOS, taking 10.4 seconds from the second click to launch the app, to display of the prompt for user approval. During that period, a standard progress dialog was displayed. Entries in the log consisted of about 13,000 messages of SecKeyVerifySignature from syspolicyd and trustd, with repeated errors of
SecError com.apple.securityd Malformed anchor records, not an array

Tahoe: Subsequent runs

The second and third runs, out of quarantine, were almost identical in the log, and similar to those in macOS 15.7 (below). com.apple.syspolicy.exec announced early that the code had already been evaluated, and those previous results would be used. Provenance data was found, and the evaluation completed without any CloudKit check of notarization. Times from the second click to launch the app, to loading of the app’s preferences were 0.64 and 0.66 seconds.

At various times, the kernel reported that it was considering a malware scan on one of the executables being checked, for example
ASP: considering malware scan (activeRulesVersion: 11716915239283693719 lastScanVersion: 0 chgtime: 1758884893 lastFileScanTime: 1758884893 threshold: 1758884893 pid: 949 info_path: /Applications/calibre.app/Contents/MacOS/calibre proc_path: /Applications/calibre.app/Contents/MacOS/calibre isNewerThanScan: 0 needsVersionScan: 0 is_time_eval_exempt: 0 is_scan_version_exempt: 1
Those appear new to macOS 26, and haven’t been seen in any log records from macOS 15.7 or earlier. Executables cited in those messages extended beyond components of Calibre to others that happened to be running at the time, but none was followed by any report of whether a scan was performed as a result.

Although they didn’t delay app launch, at the same time amfid entered the path of the main executable and 112 dylibs and others to check each individually. For the dylibs and others, each was accompanied by a report from the kernel of
AMFI: constraint violation [dylib path] has entitlements but is not a main binary
Those took a period of approximately 3 seconds in each of the two runs.

Sequoia: 2nd and 3rd runs

These were remarkably similar, and in many parts identical, to those in Tahoe, except that there were no messages reporting consideration of malware scans. Times from the second click to launch the app, to loading of the app’s preferences were slightly quicker than Tahoe, at 0.59 and 0.59 seconds. Concurrent time to iterate through all the executable components was also shorter at 2.6 seconds, with identical reports of constraint violations.

Conclusions

  • macOS 26.0 Tahoe does now skip reported XProtect malware scans when a notarized app is run for the first time, when in quarantine.
  • Despite that, first run checks undertaken in Tahoe can still take significantly longer than in subsequent runs.
  • This is the result of a vast number of SecKeyVerifySignature entries written during checks on executables.
  • Tahoe also considers explicitly whether to perform malware scans on other processes being run, although none were undertaken. These are new in Tahoe.

From this evidence, I’m not convinced of any significant improvement in launch times. Please let me know whether you think that Tahoe has improved the speed of your app launches.

Previous articles:
Why some apps launch very slowly
Gone to launch

❌