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 😟

@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"

Hi eskimo,


I DID submit an enhancement request. 🙂


The reason I replied to this dormant thread is that it is the most informational post I've found on "Full Disk Access".


I'm finding that on Catalina, even when I *DO* grant my app Full Disk Access, when I call contentsOfDirectoryAtPath on many folders (such as /Applications/Utilities) the call returns an EMPTY array and a nil error. Even though there ARE of course applictations in that folder.


Further, if I copy, say, a text file into the Utilities folder, then contentsOfDirectoryAtPath returns that file in its result but still no applications!


What gives? Why can my app not "see" ALL contents of any given folder when it has been granted Full Disk Access?

You may be right John, but what a boring world it'll be (for me)... I've always loved writing utilities that "extend" the OS features... if each app is walled off then there is no such opportunity to be "a part of the OS".... I can see the writing on the wall though... looks like my apps will have be sunsetted and my fun curtailed...

That is because you shouldn't consider the path /Applications to be an API. There are, by default, no files in /Applications/Utilities.


This is not a security issue (well, it is, but that's a long story). This is a side effect of how system files have been re-arranged in Catalina.


Why do you want to access that directory anyway? You shouldn't be copying text files there. I assume that was just a sanity check.


The files that you might see in the Applications folder in the Finder now reside, on disk, in multiple places. System files are in /System/Applications. 3rd party files are in /System/Volumes/Data/Applications. But, in most cases, your software has no business being in either. The few case where you might have a legitimate need to access /Applications, you can do so using the /Applications firmlink which will return the contents of /System/Volumes/Data/Applications. And don't forget about ~/Applications. These files aren't merged in the Finder, but they do show up in LaunchPad.


Does all this make sense? If so, good! That makes one person. 🙂

I DID submit an enhancement request.

Cool. What was the bug number?

What gives?

As john daniel explained, this is because of the read-only system volume change in 10.15. WWDC 2019 Session 710 What’s New in Apple File Systems has a bunch of background on this.

Finally, if you want to find all of these directories, it’s best not to hard code the paths, but instead using

NSFileManager
. For example, this:
let userApps = try! FileManager.default.url(for: .applicationDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
print(userApps)
let localApps = try! FileManager.default.url(for: .applicationDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
print(localApps)
let systemApps = try! FileManager.default.url(for: .applicationDirectory, in: .systemDomainMask, appropriateFor: nil, create: false)
print(systemApps)

prints this on 10.14.6:

file:///Users/quinn/Applications/
file:///Applications/
file:///Applications/

and this on 10.15:

file:///Users/quinn/Applications/
file:///Applications/
file:///System/Applications/

Share and Enjoy

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

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

The forum scrambled your output.

Indeed it did. Thanks for pointing that out.

Let’s try that again. Here’s my test code:

let userApps = try! FileManager.default.url(for: .applicationDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
print(userApps.path)
let localApps = try! FileManager.default.url(for: .applicationDirectory, in: .localDomainMask, appropriateFor: nil, create: false)
print(localApps.path)
let systemApps = try! FileManager.default.url(for: .applicationDirectory, in: .systemDomainMask, appropriateFor: nil, create: false)
print(systemApps.path)

It now prints paths, not URLs (-: And here’s 10.14.6:

/Users/quinn/Applications
/Applications
/Applications

And here’s 10.15:

/Users/quinn/Applications
/Applications
/System/Applications

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
Big Sur 11.4 has been released, and I've got an issue with one of my apps. This app includes an Helper Tool (a bundle), that is embedded in the LoginItems subfolder. This helper tool is launched thanks to the SMLoginItemSetEnabled API.

Before updating to 11.4, if user granted Full Disk Access to the main app, the Helper Tool got Full Disk Access too, as stated by eskimo.

But now, it's not working anymore. The Helper Tool does not inherit from the main app, either the Full Disk Access but also other authorisations like Automation for Finder.

Did someone find a solution to this?
The Rules for Full Disk Access
 
 
Q