You might think that when an app’s signing certificate is revoked, macOS would at least warn you when you run that app. Not so: not only will macOS Mojave 10.14.2 (and earlier macOS too) run such apps without pointing out their problem, but neither Apple nor the app vendor will have revealed when or why that certificate was revoked.
If you have a copy of Microsoft Messenger 8.0.2 around, try running it now. Unless you’ve only just downloaded it from the internet, chances are it will open quite happily. It’s only when it has a quarantine flag attached to it that it’s forced to undergo a full Gatekeeper check, which would reveal its serious signing problem. Use a tool such as Objective-See’s What’s Your Sign and you’ll see its signing problem.
To many developers and security experts, none of this is new, and several of the latter have been drawing attention to these shortcomings in the way that macOS performs signature checks. What should come as a surprise is the extent of the problem: the Applications folder on my brand new iMac Pro contains over 15,000 bundles with executable code, of which 1878 (12%) have a signature problem, in most cases being completely unsigned.
Another example is that many popular apps use the Sparkle system for detecting and installing updates. Although those apps themselves are properly signed, in almost every case the app which actually runs the update process is completely unsigned.
A few days ago, I stumbled across a really old QuickTime extension on this Mac, which I was unaware was installed. Like many Macs, its contents were migrated from a previous Mac, which had migrated from an older Mac, and so on. Although each migration checks apps and other bundles against a blacklist, it doesn’t check whether their signatures are valid, or have even been revoked.
So I thought I’d write a little app to check through bundles which include executable code and discover which have invalid signatures: Signet. I’m making it available in first beta release now, as I think that you may find it useful, and it makes the important point that macOS has a signature problem.
How it works
Signet iterates recursively through a selected folder (working the same as 32-bitCheck) looking for bundles – folders with a specific structure laid down by Apple – containing executable code. Whenever it finds one, it calls on macOS to check its signature. This isn’t as exhaustive a check as that made by Gatekeeper on an app with a quarantine flag set, but should detect the most significant errors.
Signet is not designed to look for malware, or bundles which are crafted to exploit bugs in signature-checking. If you want an app to check for malware, there are several excellent products on the market intended to do that. Signet aims to report non-malicious bundles which you may wish to be concerned about.
The sequence of checks which Signet makes on a bundle are:
- Whether the bundle is designated as executable.
- Whether its code can be examined as ‘static code’.
- Whether the static code has a valid signature according to the ‘strict validation’ (SecCSFlags kSecCSStrictValidate).
If the first is not true, Signet makes no further evaluation of the bundle, but will still look inside it to see if it contains other bundles to be checked.
Many bundles which pass that first test fail at the second, largely with an error code of 100021 (kPOSIXErrorEISDIR, an ‘illegal operation on a directory’). There is a checkbox which lets you see all those errors as well if you wish.
Those bundles which make it through the first two checks then either return no error for the third, in which case Signet looks inside them for any nested bundles, or they return an error which is reported before examining nested bundles.
When Signet checks a bundle which returns a signature problem, such as the revoked certificate of Microsoft Messenger, this is reported in the macOS log in entries such as:
07:26:00.808115 Unable to parse ticket.
07:26:00.808116 error registering ticket: -1
07:26:00.808141 com.apple.securityd MacOS error: -1
07:26:00.808200 com.apple.securityd Error registering stapled ticket: [ticket contents in hex]
07:26:00.808944 com.apple.securityd cert: WeakSignature =(leaf)> 0
07:26:00.808951 com.apple.securityd cert: WeakSignature =(leaf)> 0
07:26:00.809584 com.apple.securityd cert: WeakSignature =(leaf)> 0
07:26:00.809588 com.apple.securityd cert: MissingIntermediate =(leaf)[force]> 0
07:26:00.809593 com.apple.securityd cert: WeakSignature =(leaf)> 0
07:26:00.809603 com.apple.securityd cert: WeakSignature =(path)> 0
07:26:00.809619 com.apple.securityd cert: BlackListedKey =(path)[force]> 0
07:26:00.809766 com.apple.securityd Trust evaluate failure: [root BlackListedKey MissingIntermediate WeakSignature]
07:26:00.810094 SecStaticCode: verification failed (trust result 6, error -2147409652)
07:26:00.810098 com.apple.securityd MacOS error: -2147409652
07:26:00.810134 com.apple.securityd MacOS error: -2147409652
This is then reported by Signet as:
/Users/hoakley/Documents/test2/Microsoft Messenger.app error -2147409652 CSSMERR_TP_CERT_REVOKED
What does Signet detect?
I’ve only been using Signet for a couple of days on a single Mac, but here are some observations in addition to those above on Microsoft Messenger.
As mentioned, many third-party apps which are distributed independently of the App Store use the Sparkle mechanism to offer and install updates. This hasn’t been without its vulnerabilities in the past, and one odd feature about most (perhaps all) apps which currently use Sparkle is that one app nested within them is unsigned: Autoupdate.app or finish_installation.app, which actually runs the update process. This is normally found in the path within the app’s bundle of /Frameworks/Sparkle.framework/Versions/A/Resources/Autoupdate.app.
Many older apps such as Apple’s Aperture and the Bento database use obsolete signature formats, and return errors of -67013 “resource envelope is obsolete (custom omit rules)”.
Even current App Store apps may have signature problems with nested components: for example, I have an audio app purchased from the App Store which contains three plug-ins in its app bundle which fail Signet’s strict validation, one of which reports that “nested code is modified or invalid”.
Many accessory apps from major vendors such as Adobe and Microsoft are unsigned or have signing problems. For example, Adobe Acrobat 2015 contains two nested apps which lack any signature. A total of 12 support and accessory apps for old Adobe products which remain installed on my Mac have had their certificates revoked.
Current Microsoft Office apps (16.20) contain large numbers of proofing tools which contain executable code, but are completely unsigned.
Very many frameworks and plug-ins are unsigned or have signing problems. Some of the most serious include Apple’s Compressor.framework and Qmaster.framework stored in /Library/Frameworks, which use an ‘obsolete resource envelope’ from an old signature format, two StuffIt frameworks, Microsoft’s SilverLight Internet Plug-In which is completely unsigned, the Java Virtual Machines stored in /Library/Java, in which even the JDK 10.0.2 and its preference pane are unsigned. Most older QuickTime components have signature problems, with many lacking any signatures.
Does any of this matter?
Apple has pursued a policy where, once an app has cleared its initial Gatekeeper checks, it is forever whitelisted by macOS. Only if something changes the contents of its app bundle will Gatekeeper object to running it. In Mojave, Apple has introduced app notarization, which improves considerably on the checks and limits in High Sierra, but is still primarily focussed on those initial checks.
I think it remarkable that Microsoft or Apple decided to revoke Messenger’s certificate, but this event passed apparently without any announcement or explanation from either. What other apps and bundles of widely-used apps have also had their signatures revoked? Should we not remove such apps from our Macs, if they can’t be trusted by Gatekeeper – when it performs a full signature check?
Absent, obsolete and malfunctioning signatures are an excellent reason for removing old and unused bundles from your Mac. Now you can check for and discover them easily.
There is a known vulnerability in signature checking which means that crafted apps could slip past the check performed by Signet. As I wrote above, Signet is not intended to check for such malware. I will be testing more robust signature checking in a future version, but suspect that it will significantly slow Signet’s scans; I may make this available as an option in a future release. If you have any doubts about any specific item, I strongly recommend that you use What’s Your Sign to check.
When Signet scans bundles, it does so exhaustively, which takes significant time and memory. The checks it performs may require online validation of certificates, which can also slow them down. If you ask Signet to check any folder containing a very large number of bundles, that will be protracted, involve many signature checks, a lot of CPU time, and lots of memory too. Don’t be tempted to try it on the root folder of your startup volume, or it could take many hours.
Signet version 1.0b1 is currently only available for mac OS Mojave, I’m afraid, but it comes with full documentation and is (of course) notarized. It’s available from here: signet10b1
and from Downloads above.
I welcome your feedback, comments, and any bug reports, please.