Limit access for a file/folder to a given application

So I'm aware that Apple can designate a folder as a "data vault", and access to that folder is limited to applications that have a specific entitlement. I was wondering if there was an equivalent (or the same, I'm not fussy :) feature available to third parties, even if only during the app-store submission ?

To avoid the X-Y problem, what I want to do is have a launch agent with access to a SQLite database, and I want only that launch agent to have access. Any reads of the database will have to be done through an XPC call from the main user-facing application.

I want to store private data into that database, and I don't want there to be any way for any other application to read it. If there's a way to do that without data-vaults I'm all ears :)

I'm not sure if this is really the right place, perhaps the core-os forum would be better, but since the Apple solution is gate-kept by entitlements, I thought I'd start here :)

Answered by DTS Engineer in 872548022

There are two options available to third-party developers here:

  • Sandboxed app containers — These are protected as of macOS 14.
  • App group containers — These are protected as of macOS 15.

I have links to the WWDC sessions that introduce these protections in Trusted Execution Resources.

Neither of these is as tightly locked down as you’d like, but such is the nature of security trade-offs. And many of the MAC protected directories for Apple products, like ~/Library/Mail, have similar trade-offs, with ways around the protection like Full Disk Access or the Finder. And this is the Mac, so if the user turns off SIP then all bets are off.

IMPORTANT If you do anything with app groups on the Mac, see App Groups: macOS vs iOS: Working Towards Harmony.

where do you keep the master encryption key

My standard answer to that is the data protection keychain. That’s protected by the Mac’s code signing infrastructure. That’s pretty reasonable protection (as long as SIP is enabled).

If the data is particularly valuable, I think it makes sense to apply both of these protections, that is, use either app or group container protections and encryption with a key stored in the data protection keychain.


I tried and failed to get XPC working with a sandboxed launch agent.

Interesting. That works for me. Historically, there were only two key issues:

  • The name of the XPC endpoint must be prefixed by an app group ID.
  • The agent needs a bundle ID, which you could supply via an Info.plist embedded in the executable.

Nowadays I recommend that you not do the latter, but instead embed the launchd agent’s executable in an app-like wrapper. That gives you a place to store a provisioning profile, which is important if you want to work with app groups. Signing a daemon with a restricted entitlement explains how to set this up, albeit for a daemon not an agent.

This works best if you use SMAppService to enable your agent, which allows the system to run your agent directly from your app’s bundle.

Share and Enjoy

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

I was wondering if there was an equivalent (or the same, I'm not fussy :) feature available to third parties, even if only during the app-store submission ?

Somewhat. By default, your sandboxed app's Container folder is private. Other apps can request access and the user can permit it. And apps having Full Disk Access can read the data too.

To avoid the X-Y problem, what I want to do is have a launch agent with access to a SQLite database, and I want only that launch agent to have access.

You will need to be more precise here. By "access", do you mean both read and write access? You can prevent read access, but not write access.

Any reads of the database will have to be done through an XPC call from the main user-facing application.

Let me know if you ever get that working. I tried and failed to get XPC working with a sandboxed launch agent. So before you commit to that path, make sure you can make it work, or have a backup plan.

I want to store private data into that database, and I don't want there to be any way for any other application to read it. If there's a way to do that without data-vaults I'm all ears :)

You can always encrypt the data. That will block reading, but not writing. With checksums, you could detect tampering. But you probably couldn't detect outright erasure of the database.

Perhaps this would be a good point to ask what your ultimate goal is with this? When you put your software out onto someone else's computer, you lose a lot of control. That's just the way it is.

If you worry too much about security, and do something silly like take advice from the internet to encrypt your databases, then you're setting yourself up for a whole lot of headaches.

The goal here is to support end-to-end encryption of messages between devices. There's not much point in having E2E encryption if anything can just read the content locally :) - even if the user has to specify they can do it. Social engineering is something of an art form these days...

I could encrypt the data, but then the question becomes 'where do you keep the master encryption key'. For a launch-agent to be the gatekeeper, I don't really want the user to have to type in a password before it can read its data, neither do I want it to be dependent on network access to pull a key down from secure storage in the cloud. If the encryption key is stored in the keychain, then anything can access that key, so ...

It's just sort of frustrating to know that it can be done based on an entitlement (for example: Mail.app does exactly this) but it's not available to mere mortals ...

Thanks for the hint on the XPC/sandboxing - I'll check that out. I thought I'd done XPC with a sandboxed app before, but that was a few years ago, and things do change...

Accepted Answer

There are two options available to third-party developers here:

  • Sandboxed app containers — These are protected as of macOS 14.
  • App group containers — These are protected as of macOS 15.

I have links to the WWDC sessions that introduce these protections in Trusted Execution Resources.

Neither of these is as tightly locked down as you’d like, but such is the nature of security trade-offs. And many of the MAC protected directories for Apple products, like ~/Library/Mail, have similar trade-offs, with ways around the protection like Full Disk Access or the Finder. And this is the Mac, so if the user turns off SIP then all bets are off.

IMPORTANT If you do anything with app groups on the Mac, see App Groups: macOS vs iOS: Working Towards Harmony.

where do you keep the master encryption key

My standard answer to that is the data protection keychain. That’s protected by the Mac’s code signing infrastructure. That’s pretty reasonable protection (as long as SIP is enabled).

If the data is particularly valuable, I think it makes sense to apply both of these protections, that is, use either app or group container protections and encryption with a key stored in the data protection keychain.


I tried and failed to get XPC working with a sandboxed launch agent.

Interesting. That works for me. Historically, there were only two key issues:

  • The name of the XPC endpoint must be prefixed by an app group ID.
  • The agent needs a bundle ID, which you could supply via an Info.plist embedded in the executable.

Nowadays I recommend that you not do the latter, but instead embed the launchd agent’s executable in an app-like wrapper. That gives you a place to store a provisioning profile, which is important if you want to work with app groups. Signing a daemon with a restricted entitlement explains how to set this up, albeit for a daemon not an agent.

This works best if you use SMAppService to enable your agent, which allows the system to run your agent directly from your app’s bundle.

Share and Enjoy

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

Interesting. That works for me. Historically, there were only two key issues

I don't want to hijack the OP's question. It's just not something that I would recommend here in the forums.

I can only relate my own experiences. I spent quite a long time working on it. I read every scrap you've ever written on the topic, read all the related documentation, tried every combination of settings, and couldn't make it work.

Thanks Quinn.

For storing an encrypted key, it looks as though a private keychain access-group might work as well - so maybe a combination of the container and encryption would be sufficient.

Limit access for a file/folder to a given application
 
 
Q