How to use NSTask from a sandboxed XPC service

I have an app, well, a prototype of an app. The main app is sandboxed. The XPC service is sandboxed as well. When I try to use NSTask from the XPC service it fails with:

Code Block
Exception: launch path not accessible


The binary I'm trying to launch from the XPC is located inside the XPC sandbox folder. It has the correct permissions, and it runs fine.

If I disable the XPC service sandbox, it works. If I go back and enable it, it fails with the error from above.

Does anyone knows what's failing here and how to make it work?

Replies

What do you mean "XPC sandbox folder"? Any external tool that you are running should be either:
  1. Accessible to any app

  2. Inside your app's bundle, in an appropriate sub-directory

  3. Specified with a security scoped bookmark

There is a possible #4 with a user scripts folder, but I'm don't know much about that. I can't say for certain whether an app should or should not be able to execute a random binary inside its container (if that is what you mean by XPC sandbox folder).

How would you get this tool installed in that location? That's the stumbling block here. You can run a system app (usually) via #1. You can run your own app via #2. You can run some user-specified app via #3. You're trying something else?
I had a copy in the bundle and on first run I copy the binary to the sandbox directory. The XPC service has access to its own sandbox and I copied the binary there. The folder in question is the one specified by the documentation. The url can be retrieved using FileManager.urls(...)

I had a copy in the bundle and on first run I copy the binary to the
sandbox directory.

The system prevents a sandboxed process from creating executables [1]. It’s likely that this copy is the root cause of your problem. Why are you doing this copy? Why not run the tool directly from the bundle?

Share and Enjoy

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

[1] Well, you can create the but they end up quarantined so you can’t run them.

The system prevents a sandboxed process from creating executables [1]. It’s likely that this copy is the root cause of your problem. Why are you doing this copy? Why not run the tool directly from the bundle?

How do I remove the quarantine? How do I get the system to put those process in the same sandbox the parent is using?

I'm not running it from the bundle cause it fails from there as well, probably for the same reasons. More importantly, assume I want to download plugins from the internet, from my curated website, with helpers, and deploy them to ${sandbox}/Library/Plugins/. From what you're saying I wouldn't be able to run these?

How do I remove the quarantine?

I'm not sure what you are asking here. The quarantine is a metadata flag. You can remove it with xattr, but that is unlikely to help. You can's ship with that.

How do I get the system to put those process in the same sandbox the parent is using?

Again, you have to be careful with your terminology. I'm pretty sure you are asking about the app's container folder here, not the actual sandbox, which is a runtime environment. Obviously you could just copy files into the sandbox, but again, that's not going to be helpful. When your process spawns another process, by default, it inherits the same runtime sandbox. That isn't helpful to you either. You are asking about a system restriction which you can't change.

I'm not running it from the bundle cause it fails from there as well, probably for the same reasons.

What is this "probably"? There is no "probably" in software development. Either you know the cause, or you don't. Speculations and assumptions are only useful when you have several days where you really need to be frustrated and unproductive.

I suggest you stop here and investigate this failure. Then you will be able to run from the bundle and keep your complications separate.

More importantly, assume I want to download plugins from the internet, from my curated website, with helpers, and deploy them to ${sandbox}/Library/Plugins/. From what you're saying I wouldn't be able to run these?

Well that's a can-o-worms. What's the big picture here? Why are you sandboxing? Is this for Mac App Store deployment? Before you spend too much time on this idea, you have to make sure your app idea will pass App Review. App Review does have a category for "plugins" but it is up to you to interpret it and ensure that your app will comply. Apple won't "preclear" apps for App Review. I strongly advise making the "plugin" idea an optional afterthought that you can disable, if necessary, and still have a viable product.

If you aren't deploying via the Mac App Store, then you have more options. In no case is hacking inside your app container a really good idea. You'll have to be careful with this and structure the UI such that users can drag their plugs into the folder. Your app can conveniently open the container folder for them in the Finder, but the sandbox will cause problems due the the restriction that eskimo mentioned. But if you aren't deploying in the Mac App Store, do you really need sandboxing?

There are a number of ways, sandboxed or not, to make binary plugins "available" to your app, depending on your implementation.



Again, you have to be careful with your terminology. I'm pretty sure you are asking about the app's container folder here, not the actual sandbox, which is a runtime environment.

I am being careful. You're wrong. I'm not asking about the app container folder, I'm asking about the sandbox as a whole set of constraints. I don't want my binary to have any extra permissions other than the ones the XPC will have.

When your process spawns another process, by default, it inherits the same runtime sandbox.

Great, the only problem is apparently you can't execute them.

What is this "probably"? There is no "probably" in software development. Either you know the cause, or you don't. 

Sorry you can put two and two together. Obviously I don't know the cause, I wouldn't be asking otherwise.

Well that's a can-o-worms. What's the big picture here? Why are you sandboxing? Is this for Mac App Store deployment? Before you spend too much time on this idea, you have to make sure your app idea will pass App Review. App Review does have a category for "plugins" but it is up to you to interpret it and ensure that your app will comply. Apple won't "preclear" apps for App Review. I strongly advise making the "plugin" idea an optional afterthought that you can disable, if necessary, and still have a viable product.

I don't care about distribution right now. Having a sandbox, regardless of distribution, is better for everyone, users, developers and other apps.

In no case is hacking inside your app container a really good idea.

I don't know what you mean by hacking. I need a process to do something. It's not short. It's not unlawful.

So, all in all. Thanks for your answer: You are asking about a system restriction which you can't change. That’s all you had to say! The rest is unnecessary and unhelpful.

I am being careful. You're wrong. I'm not asking about the app container folder, I'm asking about the sandbox as a whole set of constraints. I don't want my binary to have any extra permissions other than the ones the XPC will have.

Then I suggest research how the sandbox works with respect to entitlements and inheritance so that your questions will be more clear.

Great, the only problem is apparently you can't execute them.

Speak for yourself. I can execute them just fine in the sandbox.

Sorry you can put two and two together.

As you can too. Someone with more experience in these things than both of us put together told you to run it from the bundle. You dismissed that advice because of some other, likely unrelated, problem. That's the answer. I understand that it didn't work when you tried that. But the fact there is some other problem in your code doesn't change the fact that this is the answer.

I don't care about distribution right now. Having a sandbox, regardless of distribution, is better for everyone, users, developers and other apps.

On Apple's platforms, distribution is always an important factor. I agree that the sandbox is better for users, that's why it is required for the Mac App Store and recommended everywhere else. But it is not necessarily "better" for developers as it adds complications, some of which cannot be overcome even by entitlements. However, this is just a pedantic talking point. In your specific case, you are simply doing it wrong, regardless of sandboxing or distribution. The fact that it works when the sandbox is disabled does not necessarily mean it is correct.

I don't know what you mean by hacking. I need a process to do something. It's not short. It's not unlawful.

A "hack" has nothing to do with malware or exploitations of vulnerabilities. It simply means you are doing something in an ad-hoc, non-standard way that is likely to break under a future and/or more restrictive environment. Apple regularly increases security levels in the operating system. Sometime of these changes may impose additional restrictions even on non-sandboxed apps. Apple made major changes like this in Catalina. What you are proposing is at relatively high risk of breaking in some future update.

That’s all you had to say! The rest is unnecessary and unhelpful.

Good luck then!