NSFileManager function containerURLForSecurityApplicationGroupIdentifier does not work on MacOS Sonoma

When we try to run our code that uses the containerURLForSecurityApplicationGroupIdentifier function, the returned value is null if the program was run with root privileges. (when we run the code like a normal user, it is works as expected)

The following code was run:

NSFileManager* fileManager =  [NSFileManager defaultManager];
if(!fileManager) {
	return “”;
}

NSURL* containerURL = [fileManager
containerURLForSecurityApplicationGroupIdentifier:[NSString stringWithUTF8String:group_name]];

if(!containerURL) {
	return “”;
}

-> we will receive the right containerURL:

/Users/{user}/Library/Group Containers/{group_name}

If the same code will be run with root/admin privileges the containerURL will be NULL.

With an older version of MacOS the output result was the following:

normal user: /Users/{user}/Library/Group Containers/{group_name}

root user : /private/var/root/Library/Group Containers/{group_name}

Replies

Please clarify what you mean by “if the program was run with root privileges”.

You tagged your thread with App Sandbox, suggesting that you’re building an app. But apps don’t generally run with root privileges.

Share and Enjoy

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

Sorry for misunderstanding, I put the sandbox app because we had a daemon which communicate with a “sandbox app”.

For debugging we run the daemon with root credentials: sudo ./daemon

We observed the mentioned code above is work as expected if the application was run in the following way:

./application.exe -> the output IS correct

sudo ./application.exe -> the output is NOT correct (containerURL is NULL) (this worked as expected on older macos)

Sadly, I’m still confused. Your examples show this:

sudo ./daemon

and this:

./application.exe …
sudo ./application.exe …

Are daemon and application.exe the same thing?

Also, can you clarify what you mean by “daemon”. I generally use the term to mean a launchd daemon, launched by dropping a property list into /Library/LaunchDaemons (or using SMAppService.daemon(plistName:)). Does that match your usage?

Share and Enjoy

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

Yes, daemon and application.exe are the same thing and sorry again for confusion.

If you will run this code/application with/without sudo you will option different things/results.

CODE (application.exe):

NSFileManager* fileManager =  [NSFileManager defaultManager];
if(!fileManager) {
	return “”;
}
NSURL* containerURL = [fileManager
containerURLForSecurityApplicationGroupIdentifier:[NSString stringWithUTF8String:group_name]];
if(!containerURL) {
	return “”;
}

Result/Output:

./application.exe -> the output IS correct

sudo ./application.exe -> the output is NOT correct (containerURL is NULL) (this worked as expected on older macos)

The fact that you’re seeing different results is annoying, and you are free to file a compatibility bug about that. However, I’m not surprised you’re having problems here. On the Mac, app groups are per user. If you run code as root and ask for the group’s container, you’ll get a directory within root’s home directory. That’s not useful if your intention is to share state with an app being run as the normal user.

Now, when you run code using sudo things get weird. macOS’s execution context model is very different from that of traditional Unix-y systems. If you’re curious about the details, see Technote 2083 Daemons and Agents. It’s super old, but still generally accurate. sudo only switching some part of the execution context, which results in your code running in a mixed execution context. Sometimes that yields weird results.

I’d like to take a step back here and ask about your high-level goal: Why are you trying to mix app groups and sudo?

Share and Enjoy

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

The answer is simple, we use a daemon which communicates with an user mode application. The mentioned user mode application was sandboxed which means the file sharing between daemon and other applications was restricted. The only method to communicate/shared files between the mentioned apps (daemon and notifier app) can be made using group specific folder.

When the daemon is launched using launchd command the returned value for group app is good (a path is returned) but when we debug our solution (our daemon) we don’t use launchd command, we use sudo command.

How we can detect the same group app/the same folder to share files between the daemon and user mode app (notifier app)?

The answer is simple, we use a daemon which communicates with an user mode application.

By “daemon” you mean a launchd daemon run by adding a property list to /Library/LaunchDaemons, right?

when we debug our solution (our daemon) we don’t use launchd command, we use sudo command.

This is always a mistake. As I mentioned early, sudo puts you in an odd execution environment, one that triggers all sorts of weird problems.

The mentioned user mode application was sandboxed which means the file sharing between daemon and other applications was restricted. The only method to communicate/shared files between the mentioned apps (daemon and notifier app) can be made using group specific folder.

This is where you lose me. Each user, including root, has their own container. How does that help with sharing?

Share and Enjoy

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