As part of Gatekeeper, macOS runs a code signature validation scan on all apps when they are run the first time. This results in some really large apps taking 2-3 minutes before they can run. Some apps include: Xcode, Matlab, Mathematica, etc.
The macOS installer app for Big Sur suffers from this too and as a result if you try to run “Install macOS Big Sur.app” it will take at least 2 minutes while macOS scans it. If you launch the app installer through the GUI, the app will simply bounce in the dock until the scan completes. If you run the app through the CLI using
startosinstall, it will show no activity until the scan completes.
There’s no way to force macOS to scan a particular app for its code signature validation other than actually trying to run it. This would obviously lead to a bad user experience for the end user.
As a workaround, you can trigger the code signing validation by using
startosinstall --usage. This will not actually run an OS upgrade and macOS will start to scan “Install macOS Big Sur.app” silently in the background.
I’ve written a simple script that is designed to run immediately after “Install macOS Big Sur.app” has been installed. I’ve designed it for use in Jamf Pro, but you could easily modify it for other uses if you wanted. The idea is to make the user experience better so that when the user launches an OS upgrade whether through a GUI install (as Apple intends) or a CLI install relying on “startosinstall” there’s no a 2-3 minute period of silence. You can run the script immediately after deploying the installer app to the computer.
File feedback with Apple so that they can improve this user experience and macOS installer apps can be scanned immediately after a download has taken place. This would also have benefits to other large apps as well. Jamf has a good article that discusses the various options for providing Apple with feedback.
XProtectService and syspolicyd
If you try to see what’s going on in the when you launch the installer macOS app, you will see
XProtectService mentioned in the Console logging when dealing with one of these apps and
syspolicyd. Some research on
syspolicyd that helped a bit in my testing and research: https://knight.sc/reverse%20engineering/2019/02/20/syspolicyd-internals.html
There is a Launch Daemon at
/System/Library/LaunchDaemons/com.apple.security.syspolicy.plist which seems to have the frequency at which some
syspolicyd actions might be taking place depending on the LaunchEvent. The
com.apple.security.syspolicy.find.bundles key seems to be relevant based on the name. That runs weekly (604800 secs). There is a CLI to this:
/usr/libexec/syspolicyd but it’s not very clear to me how to interface with this or whether I’m supposed to. I assume that
spctl is the tool that’s supposed to interact with
Investigating options to workaround code signing validation
For the curious, I did try a bunch of things to kick off the code signing validation before I tried to launch the app or to avoid code signing validation altogether.
The following does not work:
# Remove com.apple.quarantine recursively from app bundle
xattr -dr com.apple.quarantine "/Applications/Install macOS Big Sur Beta.app"
# Clear all extended attributes recursively from app bundle
xattr -cr "/Applications/Install macOS Big Sur Beta.app"
# Asses app
spctl -a "/Applications/Install macOS Big Sur Beta.app"
# Stop spotlight from trying to index app
mdutil -i off -a
# Register app with launch services
/Volumes/Macintosh\ HD/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -R -f "/Applications/Install macOS Big Sur Beta.app"
# Add path to app to Gatekeeper
spctl --add "/Applications/Install macOS Big Sur Beta.app"
# Not sure if using the –path option makes a difference
spctl --add --path "/Applications/Install macOS Big Sur Beta.app"
# Put label on app bundle and then enable label so that Gatekeepr will bypass it
spctl --add --label "Approved" "/Applications/Install macOS Big Sur Beta.app"
spctl --enable --label "Approved"
# Disable Gatekeeper
# Tried to modify the syspolicy database
sqlite3 /var/db/SystemPolicyConfiguration/ExecPolicy using:
INSERT INTO policy_scan_cache (volume_uuid,object_id,fs_type_name,bundle_id,cdhash,team_identifier,signing_identifier,policy_match,malware_result,flags,mod_time,timestamp,revocation_check_time)
VALUES ('C202AB2C-4F93-44BE-9F4F-CB5DA760F07E','189698','apfs','com.apple.InstallAssistant.Seed.macOS1016Seed1','45bc1b465728e65fb091f81bcc0ea147370f455f','','com.apple.InstallAssistant.Seed.macOS1016Seed1',11,0,512,1604217029,1604217029,1604217029);Error: attempt to write a readonly database
This failed because its a read-only database naturally.
# Tried to change the date more than 7 days into the future hoping that might trigger the OS to do its scanning:
date -u 1111000020
The following did work:
I did find one way to avoid the code signing validation but it cannot be automated with either CLI tools or through MDM. Go to Sys Pref > Security & Privacy > Privacy tab > Developer Tools > Enable Terminal. Going forward, no security check takes place when I run (from Terminal) the exact binary that’s supposed to get loaded.
With Terminal not enabled in Developer Tools:
/Applications/Install macOS Big Sur Beta.app/Contents/Resources/startosinstall --usage would normally take 120 secs
But with Terminal enabled in Developer Tools, that runs immediately.