Subject: Supported macOS containment for a sandboxed worker after controller failure
I'm investigating an Apple Silicon/macOS architecture in which an untrusted, signed, sandboxed worker must be independently containable by a separate trusted supervisor.
The worker needs only a narrow authenticated communication channel. It requires no direct network access, external operational credentials, privileged file access or authority to launch helpers.
I understand that App Sandbox does not inherently prevent child-process creation, and that RLIMIT_NPROC alone does not prevent every form of execution delegation.
Could you clarify:
- Is there a public, supported macOS mechanism to deny all worker-originated subprocess creation and execution delegation at launch, while retaining one restricted communication channel?
- Alternatively, is there a supported mechanism for a surviving supervisor to identify, terminate and positively verify the complete execution domain of a worker, including any descendants, after its controller crashes or is suspended?
- What guarantees and limitations apply to stable identity, process exit, automatic relaunch and loss of the supervisor?
I'm specifically seeking supported operating-system guarantees, not private sandbox profiles, polling, heartbeat inference or best-effort process-tree enumeration.
The goal is to determine whether a bounded synthetic containment experiment is technically justified. No production implementation has been attempted.
I mean the complete execution scope originating from an untrusted worker
OK.
the worker process itself, any child or descendant processes it starts, and any additional execution it can cause to run on its behalf through supported delegation mechanisms.
I’m gonna break this into two parts:
- The process hierarchy
- Any “supported delegation mechanisms”
The process hierarchy is something that Kevin has been discussing on other threads, and I’m gonna defer to him for that.
Regarding delegation, I don’t think there’s any good way for you to reason about this. Lemme illustrate this with two examples:
- A process can use Virtualization framework to start a VM.
- A process can use
NSWorkspaceto launch an app.
In the first case the Virtualization framework will clean up the VM when the process that created it terminates. In the second case that doesn’t happen. The underlying Launch Services machinery treats the launched app as a completely separate thing.
In both cases the actual work in done by system processes. However, the client doesn’t interact with those system processes directly. Rather, it calls the framework and the framework does whatever IPC is necessary to complete the task. The actual IPC mechanism is an implementation detail, not part of the API.
So, from your perspective:
- You can’t block the process from using these frameworks.
- You could potentially block a framework from performing its IPC, but you can’t do that without becoming deeply entangled with the framework’s implementation. This is going to be very brittle and certainly not something that DTS is gonna support.
- You can’t, in the general case, know whether a specific framework cleans up on behalf of its clients. Indeed, this could vary within a framework. For example, within AppKit you’ll find that a window you create with
NSWindowwill get cleaned up but an app you launch withNSWorkspacewon’t.
Taking a step back, I recommend that you have a read of TN2083 Daemons and Agents. It describes, in gory detail, how macOS’s execution context differs from that found on traditional Unix-y systems. This difference will significantly affect any attempt by you to limit the impact of code that you don’t trust.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"