Granting full-disk access to my sandboxed app not working

I'm experimenting with full-disk access to my app and can't make it working. Here is list of steps I did:


Sandbox is turned ON. In fact the entitlements file looks like:

<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>


  1. I created archive of the app and tried to distribute it using boths Developer ID or Development methods
  2. I placed the binary of my app to /Applications folder
  3. I went to System Preferences -> Security & Privacy -> Privacy -> Full Disk Access and added access to my app in /Applications folder
  4. Of course I'm NOT attached to the app with Xcode

I'm testing it in Xcode 11 and on Catalina. It's dummy app, opening

NSOpenPanel
to let user select archives to decompress and tries to decompress it in the same directory using libarchive framework.


Any hints? Am I doing anything wrong?

Accepted Reply

Thanks for the explanation.

The App Sandbox does support the concept of related files — see the Related Items section of the App Sandbox Design Guide — but this probably won’t help in this case. Most compression utilities want to be able to:

  • Accept a directory and create an archive next to that directory

  • Accept an archive and create a directory next to that archive

In both the cases the directory doesn’t have an extension, which prevents you from using the related files mechanism because that’s keyed off extensions.

There’s three ways around this:

  • Drop, or radically loosen, the App Sandbox

  • Present the user with a save panel for the output

  • Output to a directory chosen by the user up from

None of these are ideal, with the first one only being feasible if you’re distributing outside of the Mac App Store.

Share and Enjoy

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

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

Replies

The App Sandbox applies a different set of restrictions than Full Disk Access. I believe the restriction you’re hitting is being enforced by the App Sandbox itself. You wrote:

opening

NSOpenPanel
to let user select archives to decompress and tries to decompress it in the same directory

When the user selects a file in the open panel, the system extends your sandbox to allow access to just that file. That extension does not apply to the directory containing that file, so if you try to create a new file in that directory (for example, by uncompressing the original file) that will be blocked by the sandbox.

Share and Enjoy

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

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

Let's forget about NSOpenPanel for now. It was just an example. My app could work with other files, not only with those selected by user.


Let me rephrase the question:

What is necessary to do to make sandboxed app using full-disk access?

What is necessary to do to make sandboxed app using full-disk access?

That depends on what you mean by “full-disk access”? Let’s break this down:

  • Can a sandboxed app access every file on the file system? — No. The sandbox prevents privilege escalation, and lots of files have privileges that prevent access by a sandboxed app.

  • Can a sandboxed app access every file in the user’s home directory? — No. Lurking in

    ~/Library/
    are special directories call data vaults, which are only accessible by system processes. See this post for more.
  • Other than data vaults? — No. There are two further levels of protection in play here:

    • On 10.15 and later, certain common locations, like the Desktop, require Files and Folders access (see System Preferences > Security & Privacy > Privacy > Files and Folders).

    • On 10.14 and later, certain obscure locations, like the mail database, require Full Disk Access (see System Preferences > Security & Privacy > Privacy > Full Disk Access).

    The latter subsumes the former.

    These privileges can only be granted by the user.

  • What if I have these? — If your app is sandboxed, you still need a sandboxed extension to access items in the user’s home directory that are outside of your app’s container, and that means interacting with open panel (or drag’n’drop, or some other sandbox extension mechanism).

I realise that this is all very general. If you can explain more about your specific scenario, I can give more focused advice.

Share and Enjoy

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

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

Oh, thanks for your time!


I'm quite new to macOS development, most of my time I code iOS apps. My goal is to learn something new and implement a simple compressing/decompressing app using libarchive as library to do the job. Here is set of desired features:

  • app can open and decompress associated files
  • app can open and decompress drag-n-dropped files
  • app can open and decompress files using NSOpenPanel
  • app can be opened from FinderSync extension or Action extension
  • of course app can create archive from drag-n-dropped files or files selected in NSOpenPanel

I hope it's enough info for you, to be honest nothing special or secret 🙂

This is something that trips a lot of people up. In particular, end users are confused by it. Many of them have heard about Full Disk Access, so they will attempt to give it to your app, but it won't work, because of the sandbox. They don't know about that. And if you are distributing in the Mac App Store, you can't tell them either. 🙂 If you are planning on Mac App Store distribution, your app has to be fully functional without any kind of sandbox escape or Full Disk Access. You can't even show a button unless the user goes looking for it on purpose.


But generally speaking, there are two steps to accomplish. I call it "Full Drive Access" to differentiate it, and because there ain't no disks no more.


1) You will need to use an NSOpenPanel to get a reference to the root folder of the drive. You can specify the root folder and force the dialog into the correct location. And then you can check the result and make sure you really got root back. Save that as a Security-scoped bookmark and now you've escaped the sandbox. But you're not done....

2) On Mojave an later, you still need to get Full Disk Access in system preferences. You can use a handy deep link for this (x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles) to make the process slightly less painful. But you'll still need to quit the app.


So, you will have to start the process inside your app to get both parts on 10.14+. If you are running on 10.13, you only need the first part.


Another complication is that the security database can get confused. You might need to relaunch your app a couple of times. You might need to restart. Unfortunately, the machines that developers use can get these internal databases quite scrambled. I strongly recommend a VM system for Mac development. They are easy to setup and rollback. They aren't good for graphics. If you need decent graphics, you'll have to use a separate machine with liberal use of APFS snapshots for rolling back.


I use Parallels Desktop Lite just because it doesn't have host kernel extensions. (I can't recomend that product without complaining about their dirty little trick to use a minor App Store upgrade to slide in a paid subscription. I would paid for a supported and upgraded Mac App Store app and there are established, honest means of doing that. They used a tricky and sneaky method instead. I would use a different VM if I could find another one that didn't require host kernel extensions.)


In all honesty, this is not a viable, long-term solution. Customers who've already paid are invested and can be coaxed into giving privileges. It won't fly for new customers.


For your application, I suggest getting comfortable with NSTemporaryDirectory(). That will work regardless. Then get comfortable with NSOpen/Save panels and security-scoped bookmarks. You should be able to accomplish what you describe with a minimum amount of user confusion and hassle. Remember, there are some things that you will find horribly tedious because you test the app so much. Users run your app less frequently, so these daily inconveniences won't bother them as much. A big barrier like Full Disk Access with sandbox escape is going to keep them from ever being customers in the first place.

Thanks for the explanation.

The App Sandbox does support the concept of related files — see the Related Items section of the App Sandbox Design Guide — but this probably won’t help in this case. Most compression utilities want to be able to:

  • Accept a directory and create an archive next to that directory

  • Accept an archive and create a directory next to that archive

In both the cases the directory doesn’t have an extension, which prevents you from using the related files mechanism because that’s keyed off extensions.

There’s three ways around this:

  • Drop, or radically loosen, the App Sandbox

  • Present the user with a save panel for the output

  • Output to a directory chosen by the user up from

None of these are ideal, with the first one only being feasible if you’re distributing outside of the Mac App Store.

Share and Enjoy

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

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

HI eskimo,


Can you tell us what the rules are regarding Full Disk Access for NON-Sandboxed apps? All my apps run outside the sandbox.


Thanks,

Ando

The rules for file system access on 10.13.x and later are complex:

  • Or all versions of macOS, you have BSD permissions.

  • On 10.6.x and later, you have the App Sandbox. This is only required for Mac App Store apps. For other apps, it’s opt in.

  • On 10.13.x (I’m not entirely sure what the right value for x is) and later you have data vaults, directories whose access is gated by Apple-only entitlements.

  • On 10.14 and later you have the full disk access privilege (System Preferences > Security & Privacy > Privacy > Full Disk Access) which enables access to certain directories. These are typically system databases, like the mail database, that most apps don’t use.

    This is a system-wide setting.

    This can only be granted by the user.

  • On 10.15 and later you have the files and folders privilege (System Preferences > Security & Privacy > Privacy > Files and Folders) which enables access to another set of directories, this time more-commonly used ones like the desktop.

    This is a per-user setting.

    This can only be granted by the user.

    This is subsumed by full disk access.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
  • Quinn,

    Since you've written this answer, Big Sur has come out and it SEEMS to further complicate the situation: we have clients (on our non-sandboxed app) where they open a file using the system file open panel, and that works -- UNTIL sometimes they get a Big Sur update and then our app no longer has the same access permissions it had prior to the update. We know this is happening because we ultimately have to have users grant Full Disk Access permissions, just so they aren't continually hassled by this issue.

    Do you have any clarifications about Big Sur's handling of access for non-sandboxed app?

    On a related note, we want to develop and test for situations where this problem comes up, but we don't know how to revoke our app's access to any files/folders the user has ever opened. Removing/unchecking the entry in Big Sur's "Files and Folders" panel in the Privacy panel doesn't seem to reset those permissions.

    Thanks!

    Stephen

Add a Comment

It's annoying but I understand the motivation. Thanks to you and Quinn for explanation.

Can NSOpenPanel ever show a socket? e.g. /tmp/mysql.sock?

Thanks

Doesn’t look like it. It makes sense that these are hidden because the sandbox extension it would issue to you app wouldn’t be helpful (because file sandbox extensions are for file operations, not for networking).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
thanks

Hi Eskimo can you indicate whether it is possible for a Sandboxed macOS app to retain permission to files for future access. For example the user selects a folder initially and the app reads metadata from the files in the folder and keeps a database of the files. At some future point the user launches the app again and selects a database record and the app then loads that file. Currently in in subsequent file access for generating thumbnails we get the following error.

error: Error Domain=NSPOSIXErrorDomain Code=1 "couldn't issue sandbox extension com.apple.app-sandbox.read for '/Volumes/Network_Drive/Documents/samples/XXXX.***': Operation not permitted"

Is there some way for the app too retain the directory permissions so that future file reads at permitted.

Thanks

can you indicate whether it is possible for a Sandboxed macOS app to
retain permission to files for future access.

Sure, but this question is far removed from the original topic of this thread. Please put your question in a new thread, tagging it with App Sandbox.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'm trying to read gltf files which consist of json, a bin file, and a series of png images all in the same folder. How do I ship a viewer for this, if the viewer must be sandboxed, but the sandboxed app can only read the .gltf file that was supplied. The "Related Items" seems to imply the same name with different extensions, but here the image names can be anything.

Apple's ommision of gltf reader support in ModelIO requires me to supply my own reader, and I can't ask users to run usdzconvert first. But usdz has a similar file structure with separate images. All for sandboxing, except when it doesn't work. Also trying to submit this question in Chrome results in "Bad Message 431 reason: Request Header Fields Too Large". so then I had to switch to Safari.

Basically do users need to pick the folder containing the gltf, instead of the gltf file itself. Then the sandbox grants access to that folder and I can read-only any contents therein. This is rather unintuitive from the open panel to pick that. I've shipped poplular tools that had to be pulled from the App Store due to sandboxing.