Access Unix Socket from App Sandbox

Hello, I want to access the Docker socket API from inside the macOS App Sandbox. The method queries the API using curl with --unix-socket. However, the Sandbox blocks the request, as shown by the log: curl(22299) deny(1) network-outbound /Users/user/.docker/run/docker.sock Outgoing network traffic is generally allowed, but access to the Docker Unix socket is denied.

Here’s the code I’m using:

private func executeDockerAPI() -> String {
        let process = Process()
        let pipe = Pipe()
        
        process.executableURL = URL(fileURLWithPath: "/usr/bin/curl")
        process.arguments = [
            "--unix-socket", "/Users/user/.docker/run/docker.sock",
            "http://127.0.0.1/containers/json"
        ]
        
        process.standardOutput = pipe
        process.standardError = pipe
        
        do {
            try process.run()
            process.waitUntilExit()
            
            let data = pipe.fileHandleForReading.readDataToEndOfFile()
            if let output = String(data: data, encoding: .utf8) {
                return output
            } else {
                return "Error while decoding"
            }
        } catch {
            return "Error running command: \(error.localizedDescription)"
        }
    }

Is there any entitlement or sandbox configuration I’m missing to allow access to /Users/user/.docker/run/docker.sock from inside the sandbox?

Answered by DTS Engineer in 844170022

Are you sandboxing because you plan to ship on the App Store? Or sandboxing because it’s the right thing to do?

Unix domain sockets are a bit of a weird edge case:

  • You can use them for IPC between different components within your app by placing them in an app group container [1].

  • Otherwise they are blocked by the sandbox as part of its general policy of blocking unmediated IPC between code from different teams.

  • You can’t use a temporary exception entitlement to get around this because of both business and technical limitations:

    • On the business side, App Review generally won’t allow you to use temporary exception entitlements.

    • On the technical side, entitlements like com.apple.security.temporary-exception.files.absolute-path.read-write only work for files and directories; they don’t work for Unix domain sockets.

If you’re sandboxing your product because it’s the right thing to do then you can get around this by moving the code to a non-sandboxed XPC service. I talk more about this in The Case for Sandboxing a Directly Distributed App.

If you’re targeting the Mac App Store then you can’t use that option. Lemme know if that’s the case and we can talk some more.

Share and Enjoy

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

[1] Just use a short app group ID because of the path limits. We recently updated the App Groups Entitlement docs to list these limits.

What do you mean by "the sandbox"?

Do you just mean the Xcode sandbox feature or are you talking about a Mac App Store app? The difference is very important.

Since this path is outside the sandbox, obviously your app (and its child task curl) can't access it. That's the whole point of the sandbox. If this is some purpose-built, quick-n-dirty app, you could probably just give yourself a temporary sandbox exemption. Or just turn off the sandbox.

If this is a Mac App Store app and/or you want to do it the "proper" way, then you'll need a user interface to allow the user to select the socket.

PS: You might also consider ditching curl entirely and just making the connection yourself.

I’m talking about the App Sandbox that I have to enable under Signing & Capabilities for the Mac app I’m developing. I need to keep it enabled because I want to publish the app on the App Store, so simply disabling it isn’t an option.

I recently attended a one-on-one lab, and the engineer mentioned that it’s not necessarily a problem if the file isn’t inside the sandbox (which surprised me a bit). We tried to create a temporary exception for the socket file, but I’m still seeing a deny(1) network-outbound... error. Unfortunately, we weren’t able to resolve the issue during the session, so he recommended that I post the question here in the forum.

When you mention selecting the socket, do you mean creating a bookmark for it?

Are you sandboxing because you plan to ship on the App Store? Or sandboxing because it’s the right thing to do?

Unix domain sockets are a bit of a weird edge case:

  • You can use them for IPC between different components within your app by placing them in an app group container [1].

  • Otherwise they are blocked by the sandbox as part of its general policy of blocking unmediated IPC between code from different teams.

  • You can’t use a temporary exception entitlement to get around this because of both business and technical limitations:

    • On the business side, App Review generally won’t allow you to use temporary exception entitlements.

    • On the technical side, entitlements like com.apple.security.temporary-exception.files.absolute-path.read-write only work for files and directories; they don’t work for Unix domain sockets.

If you’re sandboxing your product because it’s the right thing to do then you can get around this by moving the code to a non-sandboxed XPC service. I talk more about this in The Case for Sandboxing a Directly Distributed App.

If you’re targeting the Mac App Store then you can’t use that option. Lemme know if that’s the case and we can talk some more.

Share and Enjoy

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

[1] Just use a short app group ID because of the path limits. We recently updated the App Groups Entitlement docs to list these limits.

Thanks for the detailed reply. I’m using sandboxing because I’m planning to ship the app on the App Store. More specifically, I’m planning to add functionality to connect to the local socket in one of my existing apps.

I’m planning to add functionality to connect to the local socket in one of my existing apps.

Cool. There is a path forward for this, although it may require you to update your existing app. The following should work:

  • Allocate an app group for this task.
  • Sign both apps to claim access to that app group.
  • Have the server create its listener socket in the app group container.
  • And the client connect to that socket in the app group container.

Of course, if your existing app has created the listener socket in some other location, you’ll have to update it to change that (or add an additional listener socket, if you need to maintain compatibility with existing clients).

App groups are tricky on the Mac; for the full backstory, read App Groups: macOS vs iOS: Working Towards Harmony. Either flavour of app group ID should work for this; you just need access to the container.

Oh, and don’t forget the path length limit I called out earlier. Short app group IDs are your friend.

Share and Enjoy

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

Thank you for your reply. I think my previous message might have caused some confusion. What I meant is that I want my existing app, which is already available on the App Store, to connect to the local Docker socket. I am not trying to connect to a socket that belongs to one of my own apps. The Docker socket is a system resource and not part of any of my apps, and as far as I understand, I cannot assign it to an app group

Then you'll need a user interface to select the socket file.

The temporary exception never would have worked anyway. App Review would have shot that down. And what if the user has a custom Docker configuration?

You should still keep App Review in mind. Ideally, your app should function normally and do something meaningful even if you haven't selected the docker file. If you require selecting the docker file to run, then you may have problems with App Review. I'm not saying it's impossible. But there's a good chance that, with each submission, you'll have to explain the whole background of Docker, how it works, how Unix domain sockets works, and why your app must have access to this file.

App Review is going to look at this from the perspective of dozens of other apps that try this excuse in order to directly access people's personal information. So in your UI, include a little explanation of the above. You can assume that your users know a little about Docker/Unix. But point out that they must select the actual socket file.

Technically, this would work if the user selected the root or the user home directory, but if you disallow choosing directories, then you've made it clear to both the user and App Review that this is a safe operation.

No guarantees, of course. But the more work you do up-front, the less you'll have to explain if you get rejected now or at some random date in the future.

What I meant is that I want my existing app, which is already available on the App Store, to connect to the local Docker socket.

Ah, OK. I misread “in one of my existing apps” as meaning that the socket server was in one of your existing apps, but you meant that you want to add a socket client to one of your existing apps.

And, yeah, there’s no good way to do that. Specifically, this suggestion:

Then you'll need a user interface to select the socket file.

won’t work. Lemme start by pointing you at On File System Permissions which defines important terminology.

When you use a temporary exception entitlement, it extends your static sandbox. That extension applies to both files, directories, and sockets. However, when you use the open panel to extend your dynamic sandbox, that extension only applies to files and directories, not to sockets.

Honestly, I’m not sure that this should work. The App Sandbox is all about user intent. For example, if a user drags a folder on to your app, the system assumes that their intent was to share the entire contents of that folder with your app. But Unix domain sockets are not something in the user’s world view, so it’s hard for them to meaningfully expression their intent in this case.

Of course, my opinion isn’t final here, and you’re free to make your case in an enhancement request. However, right now, there’s no good way around this limitation.

Oh, except to distribute your app directly using Developer ID signing. That’s always an option.


I recently had a discussion with a different developer about the new Containerization package, and I think the conclusion there is instructive.

Note If you’re not familiar with Containerization, watch WWDC 2025 Session 346 Meet Containerization.

The Mac App Store supports virtualisation products. Our high-level (Virtualization) and low-level (Hypervisor) frameworks are fully supported in sandboxed apps [1]. Given that, it’s possible to ship a container app in the store.

However, containers are interesting. Our containerization system is actually split into two:

It should be feasible for a Mac App store app to use the former to run a set of containers that are isolated to your app, just like any virtualisation product. However, you run into problems if you try to use the latter in an App Store app. Like in your example, it tries to use IPC to access a background process that manages all the user’s containers. That’s problematic because, in general, App Store apps aren’t allow to modify the state of the system as a whole.

So, if you want to build a Mac App Store app that manages containers that are isolated to your app, that’s a reasonable goal. But if you want to manage all the user’s containers, containers outside of your sandbox, you’re going to run into sandboxing problems.

Share and Enjoy

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

[1] Every now and again you bump into a limitation, be we try to fix them. See this thread for some examples of that.

Access Unix Socket from App Sandbox
 
 
Q