Mojave’s privacy protection, command tools, and scripts

Yesterday, I looked at how I am dealing with Mojave’s new privacy protection in my apps. In previous discussions here, we have established that the situation with respect to command tools and shell scripts is unclear and uncharted. This article attempts to explain how my command tools will cope.

Command tools are a bigger problem for Mojave’s privacy protection, because there are so many of them, both in macOS and running on it, because they generally conform to Unix conventions and expect to be able to access wherever permissions allow, and because their structure is far simpler. Yes, you can give them embedded property lists containing magic strings, but that’s not how they usually come. By definition, they also lack a GUI, although in some circumstances they can invoke dialogs provided by macOS.

My recent command tool cmpxat, which compares two files with respect to their extended attributes, could quite reasonably be applied to any two files anywhere in a Mac’s storage, within the constraints of permissions, so is a good example of a tool which needs to operate within Mojave’s privacy protected zones.

When I first ran cmpxat on two protected files, I was surprised at the result. At first, Terminal displayed a -1 as if the command was about to return an error, then came the new user consent dialog.

moprivprobs06

Note how this doesn’t give the name of the command being run, but the environment in which it is running, the Terminal app. When I clicked on OK to authorise it, the command completed normally in Terminal.

moprivprobs07

I then found, to my surprise, that macOS had automatically added the Terminal app to the list of apps authorised Full Disk Access, in the Privacy settings.

moprivprobs08

What happened in the log is also puzzling. Although cmpxat is now able to obtain access to protected items, this can throw sandbox errors in which the request appears to be denied:
00.817128+0100 Error com.apple.sandbox.reportingSandbox: cmpxat(556) System Policy: deny(1) file-read-xattr /Users/hoakley/Library/Mail/V6/D977E517-3CF5-415F-9A9C-2F2FDD63A994/INBOX.mbox/D7BCE9D7-25E3-44DF-9368-C4ED56747768/Data/Attachments/5/2/092915 APP Mac UK-Ireland v2.2.pdf
Violation: System Policy: deny(1) file-read-xattr /Users/hoakley/Library/Mail/V6/D977E517-3CF5-415F-9A9C-2F2FDD63A994/INBOX.mbox/D7BCE9D7-25E3-44DF-9368-C4ED56747768/Data/Attachments/5/2/092915 APP Mac UK-Ireland v2.2.pdf
Process: cmpxat [556]
Path: /usr/local/bin/cmpxat

But despite that error, that command completed correctly and returned the expected result.

moprivprobs09

The com.apple.TCC subsystem and tccd seldom get involved. When they do, they appear most concerned with establishing an ‘Attribution Chain’ to the calling process, which in this case is held to be the app Terminal.

moprivprobs10

The outcome may be to silently add the Terminal app to another one of the items in the Privacy list, accommodating that command and similar access in the future.

moprivprobs11

As far as I can tell at present, what happens when a user or script tries to run a command tool on one or more protected items is that TCC establishes its Attribution Chain back to an app which it recognises, like Terminal. It then behaves as if it is that app which is accessing the protected items. If that involves displaying a user consent dialog, then that occurs, giving the app as the caller.

This works well for tools called through Terminal, as it doesn’t suffer the constraints which are applied to third-party apps, even when running third-party tools. Neither the tool nor Terminal appears to be at any risk of being forced to quit, although execution of the tool will be delayed until the user has given consent in any resulting dialog.

I have two areas of concern, though.

First, once the user has consented to one tool being run in Terminal on a class of protected data, consent will not be sought again for other tools run in the same app environment. For those who only occasionally run command tools, best practice may be to uncheck Terminal in the various lists in Privacy settings, lest other command tools be given similar access without obtaining further consent.

Second, this is fine for obvious Attribution Chains going back to Terminal or the like. I presume that, if a third-party app were to call its own command tool(s), TCC would expect that app to conform to the same rules as other third-party apps, as I have described in the previous article. If you develop an app which relies on non-Apple command tools, you should be extremely careful that this doesn’t lock your tools from accessing protected items, as the user may be unable to do anything to restore that access.

I don’t know how the Attribution Chain works when there is no app at its head, for example when a command tool or service is called from a LaunchAgent or LaunchDaemon. This is again something which requires very careful testing and exploration: it would be extremely frustrating if running a backup tool at 0300 on Sunday morning invoked a consent dialog which wouldn’t be seen until 0800 on the Monday morning, for example.

The Attribution Chain is also of great significance to malware, which might use command tools and scripts to try to harvest personal data for a C&C server, for instance. The robustness of TCC and its privacy protection will determine how easily it can be exploited by such malware – which is surely one of the major justifications for all these new systems in Mojave.

For the moment, at least, there seems no need or purpose in trying to add an Info.plist to command tools, or to embed things like usage descriptions. I have been unable to find any support in Xcode for ‘hardening’ command tools, nor consequently for getting them notarized. Maybe such features will come in time, but for the moment the great majority of uses of command tools should be easy to accommodate in Mojave, and conventional builds of third-party tools should work fine once their calling app such as Terminal has been added to Privacy settings.