Distributing Outside the Mac App Store

October 6, 2016

It is said that distributing apps outside the Mac App Store is safe from meddling by Apple, because they cannot impose arbitrary rules on you or remove your apps from sale. That is true, to an extent. However, the potential still exists for Apple to put you out of business, for all practical purposes. The power to do this resides in Gatekeeper. When a user downloads your app and launches it, Gatekeeper won't allow the app to run unless it was signed by a valid Developer ID certificate. There are ways to bypass Gatekeeper, so the Mac is not completely locked down like iOS, but Gatekeeper does present a seemingly impassable barrier to the average user, so without a valid Developer ID certificate, you are unlikely to be able to sell many copies of your app.

Developer ID certificates are provided to paid members of the Apple Developer Program (which currently costs $99 plus tax per year). There is no legitimate way to get Developer ID certs for free. A Developer ID cert expires a few years after it is issued, but you can continue to renew Developer ID as long as you remain in the Apple Developer Program. And there's the catch. If for some reason Apple decided, against your wishes, to permanently close your developer account, you are at best left with a Developer ID cert that will expire within a year or two.

If Apple decided, in addition to closing your Apple Developer Program account, to also immediately revoke your Developer ID cert, then you're doomed. I'm not sure of the exact mechanism that Apple uses for passing along cert revocations to Mac users, whether it happens via normal security updates or some separate process, but we know that Apple has used the mechanism in the past against malware signed with Developer ID. Regardless of the mechanism, your potential customers will get the revocation sooner or later, and then Gatekeeper will block your apps. Fortunately, I am not aware of any instance where Apple has revoked a Developer ID cert that wasn't stolen by malware authors. The most likely scenario, then, is that Apple simply closes your Apple Developer Program account, preventing you from ever acquiring a new Developer ID cert after your current cert expires.

What are the consequences of an expired Developer ID cert? Apple outlines them on the certificates support page: "If your certificate expires, users can still download, install, and run versions of your Mac applications that were signed with this certificate. However, you will need a new certificate to sign updates and new applications." You don't have to take Apple's word for it, though, or even mine. This is fairly easy to test by advancing the system clock in Date & Time System Preferences to a date after your Developer ID cert expires. (It's probably best to reboot after doing this, to ensure that everything picks up the new date.)

In my testing, apps that were signed by a non-expired Developer ID cert are still allowed to run by Gatekeeper even if you download them after the cert expires. So you don't have to worry about old versions of your apps no longer being allowed to run because of an expired signing cert. (However, Gatekeeper requirements unrelated to cert expiration have changed in certain macOS updates, as explained in Technical Note TN2206, so there's no guarantee that your old versions will continue to run indefinitely. But the cert expiration should not be an issue.)

When it comes to updating your apps, an expired Developer ID cert is a serious problem. In my testing, I couldn't get either Xcode or /usr/bin/codesign to use an expired cert. Not even with the --timestamp=none argument. I suspect that the timestamp flag is irrelevant, because codesign seems to be failing at the beginning to even find an acceptable signing cert in the keychain. It didn't make a difference to change the Trust settings for the cert in Keychain Access to Always Trust. And it didn't make a difference to turn off OCSP and CRL in the Preferences of Keychain Access. Nothing I tried would make codesign use the expired Developer ID cert. I would be happy to be proved wrong by someone about this, but it does seem as though expiration completely prevents a Developer ID cert from being used for signing an app.

The only workaround I can think of for an expired Developer ID cert is to set your system clock back to before the expiration date when signing the app. This should work, as long as the clock change doesn't break anything else. Of course, you'd have to keep your clock in the past every time you make a build of your app. This may allow you to continue to use a Developer ID cert indefinitely for signing updates. Even if it works, though, it's not particularly convenient for app development. And if Apple got wind of your backdating, who knows whether they would take further measures to stop you, such as revocation.

While Developer ID distribution is indeed safer than the Mac App Store, there's an important sense in which you're still at Apple's mercy in any case. If your Apple Developer Program account is closed, then your days as an independent Mac developer may be numbered. The question now is, will Apple be tempted to abuse its power here? Let us pray it never comes to that. Because if it does, then divine intervention may be our only recourse.