Friday, September 30, 2016

Sandboxed Launch Services

Daniel Jalkut:

As far as I can tell, new restrictions have been placed on sandboxed apps in 10.12 that prevent such apps from using a variety of LaunchServices functions (or their NSWorkspace abstractions) that would reveal the path on disk of a specific other application.

For example, if I have BBEdit installed in ~/Applications, a sandboxed MarsEdit cannot tell that it exists. This is even though MarsEdit has an entitlement to send Apple events to BBEdit, and it can open documents in BBEdit, and BBEdit may already be running. With previous OS versions, NSWorkspace would let MarsEdit look up BBEdit by its bundle identifier, even though MarsEdit might not have access to read the returned URL. On Sierra, unless BBEdit is in the global /Applications folder, or another that sandboxed apps can read, NSWorkspace returns nil (and no error) as if BBEdit didn’t exist. Apparently, returning the inaccessible but nonetheless useful URL is considered a bug.

This is a bit surprising because we know that Launch Services is not actually scanning for applications from within the sandboxed app. Rather, it’s returning cached data that was gathered by a process with greater privileges. However, it turns out that that process verifies the privileges in the context of the application. The application only receives URLs that it can read.

My takeaways from this long Twitter conversation are:

Lastly, since this API change was not documented, I was thinking about how a developer might have detected it, other than through a bug report such as mine to Jalkut. The natural answer is unit tests. I have a lot of tests of basic OS behavior that can help detect changes and regressions. Unfortunately, as far as I know, Xcode can’t run unit tests inside the sandbox. So code that works as expected under test may not work as expected in an actual app.

Comments RSS · Twitter

Leave a Comment