macOS 27: Evaluate Endpoint Security descendants client as an alternative sandbox backend

Open 💬 3 comments Opened Aug 11, 2026 by TyceHerrman

What variant of Codex are you using?

Codex CLI and the Codex app on macOS.

What feature would you like to see?

Evaluate a macOS 27 sandbox backend built around Endpoint Security's new es_new_descendants_client API as an alternative to the current sandbox-exec/Seatbelt backend.

The API creates an Endpoint Security client scoped to the calling process's existing and future descendants, recursively. A Codex-owned client could authorize operations across that process tree without requiring each nested worker or tool process to apply another Seatbelt profile. That could avoid the nested sandbox-exec failure mode while retaining a policy-enforcement boundary around Codex-launched processes.

Why this is not a drop-in Seatbelt replacement

Codex's current Seatbelt policy starts with (deny default) and then selectively permits operations. At openai/codex@279b932, it covers more than process execution and file paths: the policy also controls IP and Unix-domain networking, sysctl, IOKit, Mach services, POSIX IPC and shared memory, PTYs and ioctls, process inspection, filesystem control operations, and other platform-specific calls (base policy, platform defaults, network policy construction).

Endpoint Security has a different model. It can deny an operation only when macOS exposes an authorization event for that operation. Notification-only events provide visibility but are not an equivalent enforcement hook. Apple's es_event_type_t reference separates those two event classes. The current macOS 27 API surface therefore appears to provide substantial but incomplete coverage:

| Relevant Seatbelt area | macOS 27 Endpoint Security coverage | Implication |
| --- | --- | --- |
| Process and filesystem policy | Authorization events cover exec, open (including an FREAD/FWRITE authorization mask), create, rename, unlink, truncate, directory reads, attributes, memory mapping, signals, and several process checks. Actual writes after open, access checks, stat, path lookup, and PTY activity are notification-only. | New opens can be denied or stripped of write access, but writes through inherited or pre-opened descriptors cannot be stopped at write time. Existence probes, path identity, and policy-cache invalidation also need explicit testing. |
| Mach services and XPC | macOS 27 adds authorization events for XPC connections and bootstrap check-in/look-up. | This is a promising replacement for relevant mach-lookup and service-registration rules. |
| Network policy | Endpoint Security can authorize Unix-domain socket bind/connect, but Apple states that it operates only on Unix-domain sockets, not sockets generally. | It cannot enforce Codex's IP bind, inbound, outbound, DNS, loopback, and proxy-routing restrictions by itself. A separate network boundary is required. |
| sysctl, POSIX IPC, PTYs/ioctls, and low-level system operations | The current event list has no documented authorization equivalent for several operations used by Codex's Seatbelt policy. | A complete replacement is not currently demonstrated. The likely outcomes are a hybrid backend or an explicitly narrower security contract. |

The documented API already establishes the broad ownership boundary: Endpoint Security can own descendant-scoped authorization for execution, most open-time filesystem access and mutations, selected process controls, IOKit, Unix-domain IPC, and macOS 27 XPC/bootstrap operations. It cannot own the complete current sandbox contract by itself because IP networking and several Seatbelt primitives have no documented authorization hook. A prototype should therefore evaluate runtime fidelity and operational viability within that supported subset, plus the complementary enforcement required for confirmed gaps, rather than treating process-tree scope as proof of full Seatbelt equivalence.

The remaining evaluation should answer:

  • What exact residual enforcement boundary follows from a control-by-control coverage matrix that maps the current Codex policy to authorization events, notification-only events, and operations with no documented Endpoint Security hook?
  • What complementary enforcement should cover confirmed gaps, especially IP networking and any unsupported sysctl, POSIX IPC, PTY/ioctl, filesystem, or low-level system operations?
  • For path-based file policy, how should the backend handle pre-opened descriptors, existence and metadata probes, symlink or hard-link identity, renames, per-process policy differences, and authorization-cache invalidation?
  • What Apple approval, provisioning, packaging, and signing changes are required for the CLI and app to ship a component with the com.apple.developer.endpoint-security.client entitlement?
  • Can Codex preserve approval, allow-rule, and escalation semantics through a centralized authorization path, including nested Code Mode tool calls?
  • What lifecycle, race, caching, deadline, failure-mode, and performance constraints appear under realistic tool and subagent workloads?
  • What fallback is required on macOS 26 and earlier, or when Endpoint Security does not cover a requested policy?

Possible acceptance criteria:

  1. Selecting the backend avoids invoking sandbox-exec for the controlled descendant tree.
  2. The minimal nested launch from #26262 succeeds while representative forbidden file writes and executions remain denied.
  3. Existing macOS sandbox policy tests either pass against the new backend or produce an explicit, reviewed matrix showing direct authorization coverage, notification-only visibility, and missing enforcement hooks.
  4. Direct IP networking remains denied through a complementary mechanism rather than relying only on proxy environment variables.
  5. Approved escalation and allow rules take effect at the intended nested command boundary, while rejected or unsupported escalation fails visibly.
  6. Deadline misses, queue pressure, authorization caching, client failure, and teardown have defined fail-safe behavior.

Motivation and scope boundaries

Several existing issues demonstrate limitations around nested Seatbelt use, but none owns this architectural proposal:

  • #26262 is the focused node_repl failure: its nested kernel launch reaches sandbox-exec: sandbox_apply: Operation not permitted. It is a concrete reproduction that this backend could test and potentially avoid, but it does not own the broader architecture decision.
  • #30615 concerns memory-worker configuration. Its targeted fixes were merged in #32197 and #32441 to rebind memory workspace roots and preserve the parent permission profile. It motivates avoiding accidental nested sandbox application, but it does not require a new backend.
  • #32848 concerns propagation of allow rules and require_escalated through nested Code Mode execution. A different backend still needs correct escalation propagation; this proposal does not replace that fix.
  • #24742 proposes extending the existing Seatbelt backend with user-provided rules. This proposal instead asks whether macOS 27 makes a different backend viable, potentially replacing Seatbelt for supported controls.

Additional information

es_new_descendants_client is new in macOS 27. Apple's current API documentation says it observes the entire descendant subtree, including processes that already exist when the client is created and processes forked or executed later. Descendant authorization and notification events are visible to the client, while unrelated processes are not.

The API requires the restricted com.apple.developer.endpoint-security.client entitlement, which must be requested from Apple and authorized through signing and provisioning. The current SDK states that a descendants client does not require root privilege or TCC approval, but entitlement and packaging feasibility still need to be proven for both the app and standalone CLI distribution paths.

macOS 27 also adds authorization events for XPC connections and bootstrap check-in/look-up, plus configurable deadline-miss behavior and per-event deadline controls. A fail-closed deadline mode can deny a covered authorization event when the client misses its deadline or its message queue is full, but it does not turn notification-only events into authorization events or cover operations absent from the event model.

Because these APIs are currently beta, feasibility and behavior should be validated against the final macOS 27 SDK and release. The requested outcome is a prototype and an evidence-backed implementation decision: use Endpoint Security as the process/filesystem/Mach layer of a hybrid backend with complementary enforcement for confirmed gaps, narrow the promised sandbox contract explicitly, or document why the current Seatbelt backend should remain.

View original on GitHub ↗

3 Comments

jdcodes1 · 9 days ago

Two additions to this (already thorough) gap analysis:

  1. The network gap has an existing in-repo answer. Codex already ships a userspace managed-network boundary — the features.network_proxy stack (codex-rs/network-proxy/) enforces per-destination HTTP(S) policy, Unix-socket allow-lists, and env-based proxy injection independently of Seatbelt. A hybrid backend of ES-descendants (process/file/XPC authorization) + the existing proxy (IP/DNS egress) covers the row your table marks "separate network boundary required" without new invention — the proxy is already the enforcement of record on Windows, where no Seatbelt equivalent exists.
  1. Distribution constraints may dominate the evaluation. An ES client needs the restricted com.apple.developer.endpoint-security.client entitlement (Apple-granted per developer account), and ES clients must run with root privileges or as a system extension with user-approved TCC/FDA. That's a materially different install story from today's unprivileged sandbox-exec profile applied at spawn — fine for the Codex desktop app (which already owns privileged helpers), awkward for the standalone CLI installed via npm/tarball in CI containers. A realistic outcome is backend divergence: app gets ES-descendants, CLI keeps Seatbelt — which argues for keeping the policy layer backend-agnostic (the SandboxManager/policy-transform split in codex-rs/sandboxing/ is already close to that shape).
TyceHerrman · 9 days ago

The existing separation between permission calculation and platform-specific sandbox construction provides a useful basis for an ES backend, but it does not solve network enforcement. Codex’s managed proxy controls only traffic routed through it. SSeatbelt permits outbound connections only to the local proxy while blocking other direct network connections, while Windows pairs the proxy with OS-level enforcement. An ES backend would therefore still need an IP/DNS boundary preventing direct connections.

Apple documents that es_new_descendants_client requires the restricted entitlement but neither root nor TCC approval. Entitlement approval, signing, packaging, and fallback remain open questions. Root/FDA are not requirements of this API, and Apple does not document a system extension as required.
A plausible hybrid would use ES for operations it can authorize, the existing proxy for destination policy, and a separate OS-level mechanism preventing direct network bypass.

jangoolie · 8 days ago

System extensions have never been a requirement for an ES client. es_new_client() and now es_new_descenants_client() are totally orthogonal to creating an EndpointSecurity Extension which is just a sort of special daemon that gets to participate in early-boot. macOS even ships with an ES client that is a command line utility (eslogger).

es_new_descenants_client() can be called from any binary with the client entitlement, no root, no tcc, doesn't have to be a daemon or an extension. It's specifically designed for standalone CLI tools like build tools and agent harnesses.