How to run apps in private

Late last year there was a lot of concern about macOS leaking information about user activities when launching apps. These centred on certificate checks which are made when apps are launched. In the past, these have normally been confined to quarantined apps undergoing their first run, but by the release of Catalina in October 2019, they have been extended to the loading of all executable code even when no quarantine flag is set.

Those checks have been performed using HTTP. Since the introduction of notarization there’s also been a second type of online check, which both ascertains whether an app has been notarized and delivers Apple a cdhash to check for known malware. Thankfully, that takes place using TLS, making any recovery of the payload far less likely.

For some users, these checks are potentially dangerous, and of serious concern. If you’re unfortunate enough to have to use your Mac in a part of the world where surveillance is performed, even knowing when you use certain apps could prove to your great disadvantage. This article looks at two potential solutions: blocking all outgoing traffic to Apple’s OCSP service, which checks certificates against its list of revocations, and removing code signatures on selected apps.

Blocking OCSP

macOS operates a fail-safe system on connections with Apple’s OCSP service: when a connection can’t be made to the service, attempts to check certificate revocation are abandoned. By blocking outgoing connections to ocsp.apple.com app launch should still proceed, usually more quickly too, without the check taking place. The great disadvantage is that blocking is all-or-none, and can’t be selective according to the app being launched. This forces the user into choosing between normal revocation checks, or none at all.

There three ways to do this:

  • in the Mac’s local hosts file,
  • in a network firewall/router,
  • in a local software firewall such as the popular Little Snitch.

Putting a block into your Mac’s hosts file is quick and simple using Terminal, with the command
sudo sh -c 'echo "127.0.0.1 ocsp.apple.com" >> /etc/hosts'
You then need to put that into effect by clearing the DNS cache, traditionally performed using
sudo killall -HUP mDNSResponder
This is readily reversed, but not the sort of thing that you’d want to perform every day. It’s also easy to set it and forget it, leaving certificate revocation disabled longer than you intend.

Blocking HTTP connections to ocsp.apple.com should also be straightforward in most network firewalls/routers. Those don’t protect when you use your Mac from outside that network, of course, which for many users makes them unsuitable.

Configuring a local software firewall such as Little Snitch has been a useful option in the past; denying outgoing TCP connections to port 80 (HTTP) of ocsp.apple.com, for both System and user of /usr/libexec/trustd, has been suggested by Jeff Johnson, but changes in Big Sur made this impossible for a while. If you’re adept with your software firewall, it shouldn’t be difficult to enable this when it’s required.

General advice from most experts is that blocking OCSP altogether isn’t something a user should choose to do unless they would be badly compromised by the revocation checks performed by macOS.

Silencing individual apps

If you don’t want to sacrifice all revocation checks, a better compromise may be to be more selective. You probably don’t care who knows when you open Microsoft Word or Pages, but do want to make your use of certain communications apps completely private.

Checks on certificate revocation can only be made on apps which are signed. If the app is unsigned, there’s no signing certificate to check. Use this to your advantage by removing the signature from those apps whose use you want to make private using a command such as
codesign --remove-signature MySecret.app
which works fine for apps running on Intel Macs.

There’s one problem with stripping signatures even on Intel Macs, though: that also removes the app’s cdhashes which are the only means of checking its integrity. You could perhaps do that using an integrity check which doesn’t rely on certificates, such as my free apps Fintch and Dintch.

Unsigned apps are an even greater problem on Apple Silicon Macs, though. Try stripping the signature from a Universal App and running it on your M1 Mac, and this is what you’ll see.

nosig01

One way to work around that is to force a Universal App to be run using Rosetta 2, which tolerates unsigned code. This is because, when Rosetta translates code, it automatically signs it with an ad-hoc signature so that it can be run by the M1’s cores. It has to do that, as the app’s original signature can’t cover the translated code. As you’ll probably prefer to run the native ARM code, try signing it yourself using an ad-hoc signature, using a command like
codesign -s - MySecret.app

As far as I can see, an app which has been ad-hoc signed still goes through the same checks as one which has been signed with an Apple-issued certificate. Its ad-hoc nature is discovered early during the launch process, with Apple Mobile File Integrity (AMFI) reporting that the app “is adhoc signed”, and amfid that the signature is “not valid” with an error of -67050. The kernel then records that “code signature validation failed”, but allows the app to continue to launch. Later, com.apple.securityd enters a security exception into the log, with a macOS error of -67018. Those two error codes have been little-used in the past.

Ad-hoc signatures make it far more difficult for anyone monitoring network traffic to identify an app whose signature is being checked against the OCSP service’s list of revocations, as well as obfuscating the secure cdhash check. But their biggest benefit is that, unlike simply stripping the signature, or blocking OCSP altogether, they still provide a cdhash so that the app’s integrity can be checked. Not as securely as fully signed and notarized apps, but much better than the alternatives.

Whatever you decide to do, please stay safe.