MacOS sandbox file permissions

I am creating a new macOS application that requires access to files outside of the sandbox. It needs to be docked in a silent state and packaged using the Electron Builder application. I have configured the relevant permissions as com.apple.security.memory-exception.files.absolute path.read-only,

It can be accessed normally in the local version of mas dev. The configuration parameters are as follows:

<key>com.apple.security.temporary-exception.files.absolute-path.read-only</key>
<array>
	<string>/Volumes/NO NAME/</string>
	<string>/Volumes/NO NAME 1/</string>
	<string>/Volumes/NO NAME 2/</string>
</array>

But during the review period of the app store, some people said it was not of legal value. The following is the original statement:

Your application is not properly sandboxed, or it contains one or more rights with invalid values. Before resubmitting the new binary file, please review the included rights and sandbox documentation and resolve this issue.

com.apple.security.temporary-exception.files.absolute-path.read-only True

If there is a com.apple.security.memory-exception.files.absolute path.read-only authorization, will the app store accept it? What do I need to do to access it?

Answered by DTS Engineer in 788959022

Hi,

I am creating a new macOS application that requires access to files outside of the sandbox. It needs to be docked in a silent state and packaged using the Electron Builder application.

I think we need to reset this conversation and start with what you're actually trying to do with these paths.

My concern here is that hard coding volume paths like this:

	<string>/Volumes/NO NAME/</string>
	<string>/Volumes/NO NAME 1/</string>
	<string>/Volumes/NO NAME 2/</string>

...is a very bad idea.

As far as the larger system is concerned, the mount directory name inside "/Volumes/" is basically an arbitrary string. On macOS, DiskArbitration (the daemon that auto-mounts volumes) HAPPENS to use a scheme that's basically "<volume name> + <number if required>", but nothing "requires" that particular scheme. iOS has replaced that scheme with a UUID value and it's also possible to directly mount (bypassing DiskArb) a volume at any path you want.

This is an area of the system where it's very easy to assume that the behavior you commonly see is how the system actually "works" and not simply an incidental default. The system intentionally provides separate metadata keys for:

NSURLVolumeNameKey-> The volume's actual name (for example, what you'd see in the Finder)
vs.
NSURLVolumeURLKey-> The location the volume happens to be mounted at.

...because they are in fact separate metadata objects that are unrelated to each other. Making ANY assumption about one of them based on the other is the kind of mistake that works fine in basic testing and then blows up later, often destroying customer data.

You need to rethink your approach here, not just in your App Store version but in any other app version you have.

-Kevin Elliott
DTS Engineer, CoreOS/Hardware

afaik that's simply not possible in the Mac App Store.

You can make the user open a directory and then store the file bookmark there to keep permission. Pre-shipping with this permission is not allowed.

Hi,

I am creating a new macOS application that requires access to files outside of the sandbox. It needs to be docked in a silent state and packaged using the Electron Builder application.

I think we need to reset this conversation and start with what you're actually trying to do with these paths.

My concern here is that hard coding volume paths like this:

	<string>/Volumes/NO NAME/</string>
	<string>/Volumes/NO NAME 1/</string>
	<string>/Volumes/NO NAME 2/</string>

...is a very bad idea.

As far as the larger system is concerned, the mount directory name inside "/Volumes/" is basically an arbitrary string. On macOS, DiskArbitration (the daemon that auto-mounts volumes) HAPPENS to use a scheme that's basically "<volume name> + <number if required>", but nothing "requires" that particular scheme. iOS has replaced that scheme with a UUID value and it's also possible to directly mount (bypassing DiskArb) a volume at any path you want.

This is an area of the system where it's very easy to assume that the behavior you commonly see is how the system actually "works" and not simply an incidental default. The system intentionally provides separate metadata keys for:

NSURLVolumeNameKey-> The volume's actual name (for example, what you'd see in the Finder)
vs.
NSURLVolumeURLKey-> The location the volume happens to be mounted at.

...because they are in fact separate metadata objects that are unrelated to each other. Making ANY assumption about one of them based on the other is the kind of mistake that works fine in basic testing and then blows up later, often destroying customer data.

You need to rethink your approach here, not just in your App Store version but in any other app version you have.

-Kevin Elliott
DTS Engineer, CoreOS/Hardware

My path is obtained through the node plugin drivelist, and when checking the source code, the underlying NSURLVolumeNameKey is used to obtain it. The path is/Volumes/NO NAME/

Just to be clear, that's only because of how you've been testing. You're right that DiskArb mounts volumes in "/Volumes/" and uses the volume name as the mount location name. SO, if you mount a single volume named "NO NAME", then that volume will mount at "/Volumes/NO NAME".

The problem here is that volume names are NOT unique, particularly with a very "generic" name like "NO NAME". Case in point, "NO NAME" is one of the names commonly used to name the FAT32 volumes that inexpensive accessories (like cameras) when the format SSD cards. In any case, when a name collision occurs, DiskArb (currently, this could always change) resolves the name collision by appending a number to the end of the mount point name. You've already run into this issue, which is why you've included multiple numbered entries.

Note that these issue are also why App Review is reluctant to grant access exceptions inside "/Volumes/". That wouldn't just give you access to "your volume", it would actually give you access to any other volume that happened to be named "NO NAME". That's particularly concerning here, since many of those volumes are likely to contain privacy sensitive pictures or movies.

Shifting to here:

Therefore, I only need to obtain the file content through the path, but I don't know how to implement it in the sandbox mode of MacOS. If you have any new ways to obtain it, can you let me know?

There are a two different options I'd suggest here:

  1. The most "direct" solution here is to have the user select the volume using an open / save panel. That's the standard solution for expanding the sandbox to specific file system locations, which is what you're trying to do here. I suspect you don't want to do that because this is part of your apps internal implementation so the user shouldn't really be involved.

  2. From the general context, I suspect that this is a disk image that's being programmatically mounted by your app and that's only used as part of your apps own internal implementation. If that's the case, then I don't think you should be mounting it in "/Volumes/" at all, as it clutters up the "users" area with directories that aren't relevant to them. Assuming that's the case, then my recommendation would be to use hdiutil (the tool used to mount disk images) to mount the image "somewhere else". hdiutil has a good man page with all the details, but the "-mountpoint" option for "attach" is the option you'd need to add. Note you should also include "-nobrowse" so the volume doesn't appear on the desktop.

Using approach #2 opens up a few other solutions:

a) I haven't tested this, but I believe that mounting the disk image inside your apps own private data container would give you full access to the volume, solving the entire issue.

b) If I'm wrong about "a" then you could ask App Review for an access exception for an application specific directory inside the user library directory. For example, something like <user home>/Library/Application Support/<app bundle id>/MyMountPoint. While I can't guarantee that would be allowed, it's a much safer option than what you've asked for before.

c) If the data is something the user will be interacting with, then you could also ask the user to select where they want the data to mount at and then user a security scoped bookmark to reuse that location "going forward".


-Kevin Elliott
DTS Engineer, CoreOS/Hardware

MacOS sandbox file permissions
 
 
Q