Skip to content

danger-full-access sandbox blocks Metal/GPU IOKit access, crashing MLX on macOS #17644

@YuancFeng

Description

@YuancFeng

Environment

  • codex-cli 0.118.0
  • macOS 26.4 (25E246), Apple M4 Pro
  • Python 3.14.2, MLX 0.31.0
  • Config: sandbox = "danger-full-access", bypass-sandbox = true, CLI alias with --dangerously-bypass-approvals-and-sandbox

Description

When Codex spawns a Python subprocess that imports mlx.core (e.g., for local voice transcription via mlx-whisper), the process crashes with SIGABRT due to an uncaught NSRangeException:

*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

The crash occurs in mlx::core::metal::Device::Device() during Metal GPU device enumeration. Metal's MTLCopyAllDevices() returns an empty array because the Seatbelt sandbox profile restricts IOKit access.

Root Cause

The Seatbelt profile compiled into the Codex binary only allows:

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient"))

This applies even in danger-full-access mode. Metal GPU enumeration requires IOKit access to GPU driver classes (e.g., AGXMetalG16X on Apple Silicon), which is not permitted.

Reproduction

Minimal reproduction without Codex, confirming the Seatbelt IOKit restriction is the root cause:

# This crashes with the identical NSRangeException:
sandbox-exec -p '(version 1)(allow default)(deny iokit-open)' \
  python3 -c "import mlx.core"

# This works fine (full IOKit access):
sandbox-exec -p '(version 1)(allow default)' \
  python3 -c "import mlx.core; print(mlx.core.default_device())"

Expected Behavior

danger-full-access mode (and --dangerously-bypass-approvals-and-sandbox) should grant unrestricted IOKit access, allowing Metal/GPU operations in child processes.

Suggested Fix

Add an unrestricted IOKit rule to the danger-full-access sandbox template:

(allow iokit-open)

Or, if a scoped approach is preferred:

(allow iokit-open
  (iokit-registry-entry-class "RootDomainUserClient")
  (iokit-registry-entry-class "AGXDeviceUserClient")
  (iokit-registry-entry-class "IOGPUDeviceUserClient"))

Crash Report (abbreviated)

Process:     Python
Parent:      codex
Exception:   EXC_CRASH (SIGABRT)
Reason:      *** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty array

Crash thread backtrace:
  CoreFoundation  -[__NSArray0 objectAtIndex:]
  libmlx.dylib    mlx::core::metal::Device::Device()
  libmlx.dylib    mlx::core::metal::device(mlx::core::Device)
  libmlx.dylib    mlx::core::metal::MetalAllocator::MetalAllocator()
  libmlx.dylib    mlx::core::allocator::allocator()
  libmlx.dylib    mlx::core::random::key(unsigned long long)
  core.cpython-314-darwin.so  [module init]

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIbugSomething isn't workingsandboxIssues related to permissions or sandboxing

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions