The Rules for Full Disk Access

Because we are still anxiously awaiting the documentation on the workings of the whitelist in System Preferences > Security and Privacy > Full Disk Access (previously Application Data in earlier betas), I report the following experimental results with macOS 10.14 Beta 7 (18A365a): [Edit 2018-08-22: Beta 8 seems to be the same.]


  • If I click the + button under the whitelist and enter my .app, it gets access as expected, but only if it is located in /Applications, and not attached to by lldb (not running in Xcode).
  • Even if the full path to a command-line Helper tool which my app contains (/Applications/MyApp.app/Contents/Helpers/MyHelper) is explicitly entered into the Full Disk Access list (*), and it appears in the whitelist separately from my .app, this command-line tool will be denied access when it runs. (Access worked in macOS 10.14 Beta 3. Beta 4 broke it.)
  • After I similarly enter /Applications/Arq.app/Contents/Library/Arq Agent.app into the whitelist, overnight backups in the background by the backup app which I use, Arq, start working again.
  • If I have one copy of a .app already entered into the whitelist, and + add another copy, the whitelist silently remains the same, showing only one entry for the duplicated app. (Unfortunately, the whitelist does not show an item's path in any way – no tooltip.)


Therefore, I conclude that, in order for a executable to be granted Full Disk Access, it must be…


  • the main executable of a whitelisted .app, although it is OK for this whitelisted app to be a helper/child of another app, located in the parent app's Contents/Library.
  • not attached to by a debugger.
  • located within /Applications.


Although whitelisting a certain .app will enable its main executable and any child processes, it will not enable a helper/child app when the helper/child is launched by others in the background. The helper/child must itself be explicitly present in the whitelist.


* * *


If anyone can confirm, deny, or elaborate on these conclusions, I would really appreciate it. There is maybe only four weeks to go, and it appears that I have a lot of work to do. Was the breaking of command line tools in Beta 4 intentional?


(*) To enter a helper component such as this into the whitelist, because the navigation sheet presented by the + button will not navigate into .app packages, the user must hit the + button, then ⌘⇧G, then enter the absolute path to the helper.


P.S. to other developers: The new restrictions are apparently implemented with System Integrity Protection (SIP). You can still debug your app if you disable SIP 😟

Hi, thank you very much for your reply.


I thought that using the bundle identifiers describing the dependance of the main app and its helpers located else where as you explained on August 23, would allow us to keep our architecture and let the user allow only one App, the main app located in /Applications/MyCompany/MyProduct.app. (Plan A.)


I actually have already tried both approaches yesterday that you mention in your reply, but since we would like to have to ask the user to allow only the main application, we have preferred the first approach by moving the helper tools into the App bundle. (Plan B).

The problem is that we ran into another issue: When establishing the connection via XPC, the helper tools check the requesting clients by verifying their signature and if they are signed by us. The point is that on some machines (but not all), the signature check fails for no good reason. The issue has been described by tartempion on Sep 24, 2018 7:26 AM.


Beside this issue, this solution has another drawback: The exact location of the helper tools have to be defined in their plist files located in /Library/LaunchDaemons/ what means that the App must not be moved around by the end user. (Note that other clients outside the main app also have to communicate via XPC with the helper tools.)


Beside moving the helper tools to the MacOS folder of the main app, I have also tried not to move them from their original location, and have added instead symbolic links to the app's MacOS folder which point to the actual tool locations (with their corresponding plist files in /Library/LaunchDaemons/ pointing to the link files themselves inside the app). Doing so also makes it possible to allow the tools by only allowing the main app as if the tools were really located inside the App, but this solution is also affected by the "signature issue" and has the same drawback (the app must stay in place).

The later is not dramatic, and meanwhile I am implementing a plan B to plan B in case signature check fails...

But my best wish would be actually to have a clean solution to plan A!


I have also tried to put a bundle with the helper tools inside /Library/PrivilegedHelperTools/

This did not make it possible to enable them by only enabling the main App despite the bundle identifier rule being applied.


Thanks again,

Marc

I thought that using the bundle identifiers describing the dependance of the main app and its helpers located else where as you explained on August 23 …

That’s not my current understanding of how things actually work.

When establishing the connection via XPC, the helper tools check the requesting clients by verifying their signature and if they are signed by us. The point is that on some machines (but not all), the signature check fails for no good reason.

I’ve investigated issues like this in the past and they almost always boil down to permissions issues. However, it’s hard to be sure without digging into the details.

Beside this issue, this solution has another drawback

If the helper tools run with privileges that you must copy them to some fixed location inside the file system. Putting them inside your app can result in admin-to-root privilege escalation problems, because an admin user can typically move apps around.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Since it's not mentioned in the discussion so far: Which apps do need this Full Disk Access set so they have unlimited access? Any app under Mojave, or only those that are sandboxed, or only those built with the 10.14 SDK?


Ah, it appears it's certain directories that are completely protected from access by ANY app, see: https://eclecticlight.co/2018/09/17/managing-mojaves-privacy-protection-privacy-controls/

Any app running under Mojave needs Full Disk Access for any of these locations. App Store distribution will mean more difficulties getting that past App Review.


I'm not sure how you are interpreting that web site. There are only a few directories covered by Mojave's new access methods. For the most part, these new restrictions make perfect sense. But otherwise, there is a fairly complex system that controls file system access on macOS. You have POSIX permissions, ACL, SIP, API access, and now filesystem access. Any one of which could block your app.


The writing on the wall is pretty clear. We all need to find a way to make money with iOS-style apps.

I just discovered another facet to this thing. Among the other restrictions introduced in Mojave are new additional restrictions on sending Apple Events to other apps. You might think I am going off topic of Full Disk Access but bear with me. Specifically, nonsandboxed apps using the old NSAppleScript class to send Apple Events in Mojave find that they are blocked. The app gets an AppleScript error saying so, but the dialog asking the user to grant access (which is displayed in System Preferences > Security & Privacy > Automation is never displayed. You the developer can fix this in nonsandboxed apps by removing calls to NSAppleScript and replacing them with calls to NSUserAppleScriptTask instead. With this fix, the dialog is presented, your app gets a checkbox in Automation if the user approves, and Apple Events can flow, although it seems that the dialogs may be shown repeatedly.


Since my apps use NSAppleScript, they were broken in this way, although since this breakage affected a not-so-essential feature, I did not try to fix it until today. With this fix, my XPC helper uses NSUserAppleScriptTask to get, set, and then again set the URL of the frontmost tab in Safari, and then my XPC helper process relaunches. The Apple Events worked OK, but I found that after this sequence, both my main app and the XPC helper no longer have Full Disk Access, even though the their Full Disk Access checkbox is still checked. To restore Full Disk Access, the user must switch my app's Full Disk Access off and then back on, and of course relaunch both my main app and its XPC Helper.


Since this is of course unacceptable, I completely removed the not-so-essential feature which accessed Safari via NSUserAppleScriptTask and now my app's Full Disk Access is permanent again.


I conclude that there is some "crosstalk" between the Full Disk Access and Automation features. I wonder if this was intentional or not.

I’m not sure what’s going on with this ‘crosstalk’ issue — that’s way too complex to deal with in the context of DevForums — but your Apple event issue has a simple solution: Apps built with the 10.14 SDK that send Apple events must include a

NSAppleEventsUsageDescription
entry in their
Info.plist
that explains that usage. If it’s missing, Apple events just fail without displaying the authorisation dialog.

Once you include this string your old

NSAppleScript
code should work.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you, Quinn. Unfortunately, the

NSAppleEventsUsageDescription
thing does not seem to work for NSAppleScript in nonsandboxed apps. Please watch the 3-minute video at youtu.be/GBUkIcOG7IA. The demo project is at github.com/jerrykrinock/AppleScriptTest.


(Sorry I had to strip the h-t-t-t-p-s-colon-slash-slash to avoid moderation. For posterity, I shall reply to this message with complete hyperlinks but it may take many days to show up.)

Thank you, Quinn. Unfortunately, the

NSAppleEventsUsageDescription
thing does not seem to work for NSAppleScript in nonsandboxed apps. Please watch this 3-minute movie which runs this demo project.

UPDATE: I have not tested this yet, but I think maybe it is possible that, in addition to including

NSAppleEventsUsageDescription
in Info.plist , for NSAppleScript to work in a nonsandboxed app in Mojave it must also be built with an Entitlements file containing a dictionary for `com.apple.security.scripting-targets`.


If true, since maintaining this dictionary looks to be quite painful and bug-prone, I think I shall stick with my workaround of using NSUserAppleScriptTask, especially given that I spent the last day and a half changing all of my synchronous NSAppleScript calls to handle the asynchronous result of NSUserAppleScriptTask 😕.

@jerrykrinock, I have a similar problem in my app, I have a command-line helper (not an app bundle) that is installed as a privileged helper tool using SMJobBless. The tool is distributed with my app in its app bundle at /Content/Library/LaunchServices. I've just discovered that on Mojave my helper tool, even thought it's run as root, doesn't have access to the certain restricted privacy folders, even when I include the main app into the "Full Disk Access" list.


I tried to add my helper tool manually to this list, but it doesn't work: drag-and-drop to the Settings dialog is rejected, and you can't select the binary file in the Open dialog. Is this because it's a command-line tool and not an app bundle tool?


Nevertheless, I noticed, that Carbon Copy Cloner also has a similar helper tool (com.bombich.ccchelper) which *can* be added to the list, even though it doesn't appear an app bundle per se. How can this be possible?


Next, do I understand correctly that if I convert my helper tool into an app bundle, there will be no need to include it separately into the "Full Disk Access", it will be enough to add the main app only? Are there any additional requirements to make it work? And if so, why CCC has to do it (include the helper separately into the list)?


Finally, I'm a little puzzled, how do I convert my existing command-line helper into an app-bundle helper in Xcode? Any hint would be appreciated!

@Sheldon15, your first paragraph confirms everything I discovered by experimenting. Full Disk Access seems to be under the wing of System Integrity Protection, so indeed being root does not help.


Regarding the issue that you could not manually add your command-line tool to Full Disk Access, that was the case with my tool, however I did not try very hard to make that work because I was not about to tell my users to show package contents > Contents > Helpers, and add this tool. However, just for fun, tonight I tried to add some binaries and scripts from a folder of about 200 I've collected over the years, most written by my, some by others, and I found that when I clicked the [+] button under Full Disk Access, it would allow me to add any of them that had no file extension, and it would allow me to drag in any of them, even if they did have a file extension! Here is a link to a screenshot to prove it. As usual, link is disguised to avoid moderation.


https colon slash slash sheepsystems.com/engineering/FullDiskAccess-CLTools.png


Of course, I'm using macOS 10.14.2 (18C52a), and was using betas back in August and September. So it appears to me that Apple has relented, and this is not too surprising because I got the impression that the exclusion of command line tools starting in Beta 4 was unintentional. So I am not surprised about Carbon Copy Cloner, and wonder why it does not work for you. I just checked and my SIP is on.


Regarding whether or not conversion to an app bundle is sufficient, that was originally suggested by me back in August – I was advised to just fake it by putting my command line tool into a bundle, but when running just invoke it as it always had been, by some launchd triggers. (My tool had been responding to file system changes date/time). But it did not work. What I have found to work quite reliably is to make my helper a Login Item, enabled by SMLoginItemSetEnabled(). But again, this was back in September, and things might be different now. I recommend you open a Code Level Technical Support Incident with Apple DTS.


Regarding how you do this in Xcode, it depends what you conclude. You need a working proof of concept first.

I have not tested this yet, but I think maybe it is possible that, in addition to including

NSAppleEventsUsageDescription
in
Info.plist
, for
NSAppleScript
to work in a nonsandboxed app in Mojave it must also be built with an entitlements file containing a dictionary for
com.apple.security.scripting-targets
.

Did you mean to write “sandboxed” in the quote above? Because as written this doesn’t gel with my experience at all. The

com.apple.security.scripting-targets
entitlement only makes sense for sandboxed apps. A non-sandboxed app has no restrictions on its Apple event, and hence AppleScript, usage.

I just tried this here in my office:

  1. I created a new test app from the Cocoa App template.

  2. I used the Capabilities editor to turn off sandboxing (it’s on by default in the template).

  3. I added

    NSAppleEventsUsageDescription
    to my
    Info.plist
    .
  4. I wired up a Test button to the following code:

    let scriptSource = """
        tell application "Safari"
            URL of current tab of window 1
        end tell
        """
    
    
    @IBAction
    func testAction(_ sender: Any) {
        let script = NSAppleScript(source: scriptSource)!
        var error: NSDictionary? = nil
        let resultMaybe = script.executeAndReturnError(&error) as NSAppleEventDescriptor?
        guard let result = resultMaybe else {
            print(error as Any)
            return
        }
        print(result)
    }

    .

  5. Clicking the Test button shows that it works as expected, printing:

    <NSAppleEventDescriptor: 'utxt'("https://forums.developer.apple.com/thread/107546")>

    .

[Oh my goodness, I’ve accidentally posted the URL of the page I was on while testing this! (-: ]

It’s possible that you’re referring to the hardened runtime rather than the sandbox. If so, then yes, if you enable hardened runtime then you do need an entitlement (

com.apple.security.automation.apple-events
) to access Apple events. I tested that as well, by enabling hardened runtime and then Resource Access > Apple Events in the Capabilities editor, and my app continues to work as described above.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

To be honest, what we utility developers REALLY need, is a single API call where we specify the:


a) system access capabilities our app REQUIRES to operate; and


b) system access capabilities that HELP our app to operate, but are not required...


...and then APPLE would provide a secure and informative UI to ask the user for permision to all a) and b) capabilities, and then return the results of which capabilities we were granted and which not.


I totally support the idea that Apple is tightening security, but with every new release of the OS, we are spending MORE and MORE of our time dealing with asking the user for access, informing them why, etc. instead of working on the features of our app.


The sheer amount of effort required to work in the more and more restrictive environment is seriously causing me to consider end-of-lifing my apps. And I surely hope Apple does not want to see developers abandon its platform...


Ando

You are replying to a long-dormant thread.


If you haven't already noticed, Apple has no shortage of either apps or developers. My advice is always to consider how your app would run on iOS. That's your future. Deal with it.

To be honest, what we utility developers REALLY need …

If you want to to get your requirements in front of folks who have the power to enact change, I encourage you to put them in an enhancement request.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
The Rules for Full Disk Access
 
 
Q