I’m attempting to make an app that uses Disk Arbitration to intercept a disk mount (by creating and returning a dissenter in the appropriate callback) and then mount the disk with certain options (specifically, read-only, nobrowse, or both, depending on user options). For example:
DADiskMountWithArguments(disk, nil, DADiskMountOptions(kDADiskMountOptionDefault), nil, nil, kReadOnly)
…where kReadOnly
is a pointer to an array only containing a “rdonly” CFString.
While DADiskMountWithArguments seems to be usable in a sandboxed app for disk images, it doesn’t work when the disk is an external disk (e.g. connected via USB). I see lines like this in Console.app when this happens:
Sandbox denied authorizing right 'system.volume.external.mount' by client '/path/to/exe' [17934] (engine 580)
I’ve identified two workarounds that allow this to work in a sandbox, but both have their own problems:
- If a LaunchDaemon (even a sandboxed one, which is required for registration with SMAppService.daemon from the sandboxed app) does the call to DADiskMountWithArguments, it will succeed. But App Store policies don’t allow escalation to root.
- If I use the undocumented entitlement
com.apple.security.temporary-exception.sbpl
with a value of(allow authorization-right-obtain (right-name "system.volume.external.mount"))
, the mount works without escalation to root. But I understand that App Review is likely to reject the use of this entitlement, and that this entitlement isn't supported to begin with.
Specifically, these are the behaviors I see on macOS Sequoia 15.3.1 and Xcode 16.2.
Since I would like to try to publish this app on the App Store, neither of these seem like acceptable solutions.
I don’t see why this should be restricted if the sandboxed app is not declaring a special path (i.e. the path in DADiskMountWithArguments is set to nil) and still does not have access to the mounted filesystem - am I missing something/is there a way to accomplish this?