title: Mac app extension calling connect on Unix socket gets EPERM (sandbox?)
body: <p>I'm working on a large-ish Mac app, which is split across many components in many different processes. One of those components is a Safari Extension Companion[1], which is is a kind of "App Extension" that allows a JavaScript -based extension to talk to native code (this is required for secure IPC between our components). The IPC channel is a Unix domain socket in the user's <code>~/Library/Application Support/&lt;APPNAME&gt;/</code> directory. For legacy reasons, the Unix socket server speaks HTTP and the client library for it uses a custom <code>URLProtocol</code>, in case that matters.</p>
  
  <p>This works fine for all of our other components, but none of them are running in a sandbox[2]. However, the Xcode template for the extension companion created a sandbox, and while the companion loads if sandboxed, it seems to <em>require</em> the sandbox. I tried setting <code>com.apple.security.app-sandbox</code> to <code>false</code> in the entitlements file, or removing the entitlements file (and all references to it), both appear to prevent Safari from loading the companion at all (it still runs as its own binary if directly invoked, but Safari apparently won't touch it).</p>
  
  <p>I've added exceptions to the sandbox to allow it to access the relevant directory, and just the IPC socket directly; but that doesn't seem to be sufficient. The error I get when trying to open the socket is <code>EPERM</code> (Operation Not Permitted), which doesn't really explain the problem.  After adding the exceptions to the entitlements and fixing up the paths, things like the log file (also under the "real" <code>~/Library/</code>) now get written to as expected.</p>
  
  <p>This error happens on the <code>connect</code> call for the socket (it returns -1, indicating an error, and <code>errno</code> is 1 (<code>EPERM</code>)) so there's never actually an attempt to write to or read from the socket. This seems very odd to me, since - according to the <a href="https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24" rel="nofollow noreferrer">Apple Sandbox Design Guide</a> - </p>
  
  <blockquote>
    <p>UNIX domain sockets are straightforward; they work just like any other file</p>
  </blockquote>
  
  <p>with regard to sandbox exceptions.</p>
  
  <p>The entitlements file (modified from the auto-generated template using the answer <a href="https://stackoverflow.com/questions/10952225/is-there-any-way-to-give-my-sandboxed-mac-app-read-only-access-to-files-in-lib">here</a>:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
  &lt;plist version="1.0"&gt;
  &lt;dict&gt;
      &lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;
      &lt;true/&gt;
      &lt;key&gt;com.apple.security.files.user-selected.read-only&lt;/key&gt;
      &lt;true/&gt;
      &lt;key&gt;com.apple.security.network.client&lt;/key&gt;
      &lt;true/&gt;
      &lt;key&gt;com.apple.security.network.server&lt;/key&gt;
      &lt;true/&gt;
      &lt;key&gt;com.apple.security.temporary-exception.files.home-relative-path.read-write&lt;/key&gt;
      &lt;array&gt;
          &lt;string&gt;/Library/Application Support/{APPNAME}/&lt;/string&gt;
          &lt;string&gt;/Library/Application Support/{APPNAME}/ipc_socket&lt;/string&gt;
          &lt;string&gt;/Library/Logs/{APPNAME}/&lt;/string&gt;
      &lt;/array&gt;
  &lt;/dict&gt;
  &lt;/plist&gt;
  </code></pre>
  
  <hr>
  
  <p><strong>Is there a way to make a Safari Extension Companion work without sandboxing it at all? If not, how do I allow the companion to use the IPC socket anyhow?</strong></p>
  
  <p><strong>Alternatively, is there a way to use UNIX sockets in extension companions (if the problem isn't the sandbox per se)?</strong></p>
  
  <hr>
  
  <p><strong>*EDIT:</strong> This question has been edited as a prior problem - <code>ENOENT</code> (File Not Found) when calling <code>connect</code> - was resolved before it got any comments or answers. It was due to the <code>sockaddr_un</code> being too short for the full domain socket path, and was resolved by using the real path to the socket, rather than the (very long) path through the sandbox's version of <code>Library/Application Support</code> and the symlink planted there. However, the new problem appears to be in the same place and likely also due to sandboxing.</p>
  
  <p><strong>EDIT 2:</strong> Updated the entitlements to include network client (and server, for good measure). Although the Unix socket is <em>not</em> a network socket, it is a network API that is failing, so I thought it might help. Made no difference, though; still get <code>EPERM</code> on calling <code>connect</code>.</p>
  
  <hr>
  
  <p>[1] Using an Extension Companion rather than a native-code Safari App Extension because the background/global logic is fairly complex but currently basically identical across all major browsers; re-writing it in native code would be a major one-time task and also an ongoing maintenance burden. I also suspect it wouldn't help with the problem I'm having. </p>
  
  <p>[2] The two main ones <em>cannot</em> be sandboxed, as they require access to the entire file system. The app is not distributed through the App Store, so the lack of sandboxing doesn't present compliance problems. I'd like to enable the sandboxing, for security, but it isn't practical.</p>