Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

NSTask-launch path not accessible

I'm trying to launch a command line app from my objective C application (sandboxed) using NSTask and I keep getting "launch path not accessible"

Here is the path: [task setLaunchPath:@"/usr/local/bin/codeview"];

I have set the appropriate attributes for codeview and it is working perfectly when I use it from the command line and /usr/local/bin IS in the $PATH

I know I have NSTask configured correctly because this WILL work: [task setLaunchPath:@"/usr/bin/hexdump"];

With the exception being that I'm using a command already in /usr/bin. But I can't copy codeview into /usr/bin due to SIPS.

I've tried moving codeview to various other non-SIPS protected locations all to no avail. Must all NSTask commands come from /usr/bin? Where might I put codeview so that it can be launched.

Today I'm going to use an older computer and disable SIPS to put my command in /usr/bin and see if that works. If it does. I will do it on my main machine.

Answered by Etresoft in 835956022

What are you trying to do - at a high level?

The application sandbox restricts access to certain paths. That's the whole idea. If an executable is already part of the operating system, then you can probably access it. However, command-line tools may not run properly from the sandbox.

Normally what you would do in this situation is include the "codeview" binary, if possible. Another option would be to give the user the option to specify executables to run. Then the user could select that path in /usr/local. But again, you have to hope the tool works when running in the sandbox.

What are you trying to do - at a high level?

The application sandbox restricts access to certain paths. That's the whole idea. If an executable is already part of the operating system, then you can probably access it. However, command-line tools may not run properly from the sandbox.

Normally what you would do in this situation is include the "codeview" binary, if possible. Another option would be to give the user the option to specify executables to run. Then the user could select that path in /usr/local. But again, you have to hope the tool works when running in the sandbox.

Accepted Answer

"codeview" is a third party command line utility to parse information out of a binary file. I eventually got it to work by copying the utility (post build) into the Apps package folder under <APP>/Contents/MacOS, the same place where the APP executable is. Then in APP i get the path using thisbundle for the NSTask launchpath. Here is what I found along the way that might help someone else:

  • Even disabling SIPs and logging in as the root user, I was unable to copy the file or any file to /usr/bin. That's some serious security. So why is there even an option to disable SIPs at all if I still can't change these areas.
  • Also got it to work by setting App sandbox for any of the user folders: Downloads, Pictures, Music, and Movies to "read only" or "read/write". (see photo). and move the utility to one of them. But this is not where I wanted it to be.
  • Interestingly. I created a command line utility to test this separate from a sandboxed app, and it worked just fine from /usr/local/bin.

I would prefer to have it in /usr/local/bin, which is where I have several of my own command line utilities. This way, it's in the path and I can use it in a terminal window and from within my APP.

Even disabling SIPs and logging in as the root user, I was unable to copy the file or any file to /usr/bin. That's some serious security. So why is there even an option to disable SIPs at all if I still can't change these areas.

There is more to SIP than just directory permissions. In the past, you could have done this by disabling SIP.

Apple is a curious case of the Schrödinger's company. It is both alive and dead. Everyone is obsessed with having the very latest version of every Apple software update. But at the same time, they expect that nothing has ever changed, or should ever change, in the operating system.

At least, this is the perspective from the internet at large. When developing for Apple platforms, it is better to use the current documentation from Apple instead of searching the internet. The internet is a source of frustration and misinformation.

Also got it to work by setting App sandbox for any of the user folders: Downloads, Pictures, Music, and Movies to "read only" or "read/write". (see photo). and move the utility to one of them. But this is not where I wanted it to be.

This is not a viable solution. Unfortunately, since you've just posted it on the internet, someone in the future is going to try it and then get frustrated when it gets rejected by App Review.

Interestingly. I created a command line utility to test this separate from a sandboxed app, and it worked just fine from /usr/local/bin.

Yes. That's how the sandbox works. But don't get too excited. Turning off the sandbox does enable access to more locations in the file system, but not all locations.

I would prefer to have it in /usr/local/bin, which is where I have several of my own command line utilities. This way, it's in the path and I can use it in a terminal window and from within my APP.

You can always modify your path. But I want to re-iterate that this app might not function properly in the sandbox. Consider the difficulty that you've had when trying to run your app from the sandbox. The developers of the "codeview" app have probably never tried to run it from the sandbox. If you experience any problems, they will be unable or unwilling to help.

This is not a viable solution.

You're right. it's not a viable solution, but at least it works. After a few frustrating hours of experimentation and Google searches, all failing, the Downloads folder was the thing I tried that finally worked, letting me know it was possible to use a non-system external utility, even if I didn't create it myself.

This APP is not for sale. It's something I use personally. And right now, inserting the utility into the package folder works. So until a more Apple approved solution presents itself. I'll stick with it.

Like I said, I'd prefer it to be in the /usr/local/bin folder, but that's apparently not an option anymore. Or am I wrong?

After a few frustrating hours of experimentation and Google searches, all failing

That is the path to frustration and failure.

I'd prefer it to be in the /usr/local/bin folder, but that's apparently not an option anymore. Or am I wrong?

You're wrong. It can be anywhere you want.

But you have to remember that Apple's toolchain is not designed for personal apps. Xcode is designed to build apps that will be distributed to end users. The Command Line Tools are intended to build command line tools locally.

Your usage doesn't fit into either of those categories. You're building an app. But you're sandboxing it, as if you were going to ship it in the Mac App Store. Because you are building it for the Mac App Store, you have to conform to those expectations.

But if you don't ever intend to distribute it in the Mac App Store, then you can adjust your expectations. You can turn off sandboxing. Because you seem to be incorporating a 3rd party tool, I strongly recommend this option. As I've said repeatedly, you don't know if this tool will work properly in all situations when run from the sandbox.

More generally, there are still other methods to directly access any path or executable. If you're not distributing in the Mac App Store, but you want to keep the sandbox turned on, you can simply give yourself a sandbox exemption for this path. Another option is to provide a simple UI to allow the user to directly pick a file in /usr/local/bin, or anywhere else for that matter. You might even be able to do this in the Mac App Store.

There are many options, and they are all documented, just not on the internet.

Etresoft’s offering great advice, as I’ve come to expect.

However, be careful about this:

Another option is to provide a simple UI to allow the user to directly pick a file in /usr/local/bin, or anywhere else for that matter.

That’s not feasible in a sandboxed app. When the system dynamically extends the sandbox — as a result of displaying an open panel, drag’n’drop, resolving a security-scoped bookmark, and so on — it only extends it for read or read/write access. It doesn’t extend it for executable access. This means it’s not possible for a sandboxed app to run a tool from a user-selected directory.

I talk about this, and a lot more besides, in On File System Permissions.


Wayne0737, If you continue down the sandbox path, check out App Sandbox Resources. It has a bunch of useful info, including a link to The Case for Sandboxing a Directly Distributed App. That expands on Etresoft’s “give yourself a sandbox exemption for this path” point.

But, honestly, if I were in your situation I’d disable App Sandbox and move on with my day (-:

Share and Enjoy

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

NSTask-launch path not accessible
 
 
Q