Sandbox: granular Mach IPC control — the sandbox is all-or-nothing today

Resolved 💬 3 comments Opened Mar 28, 2026 by gsalakirov Closed Apr 1, 2026

The problem: no middle ground

The macOS sandbox currently offers two modes: fully sandboxed (Seatbelt blocks everything not explicitly allowed) or fully unsandboxed (dangerouslyDisableSandbox: true). There's no way to selectively relax one aspect of the sandbox while keeping the rest enforced.

This becomes a real issue when a command needs one specific capability that the sandbox blocks. Today the only option is to disable the entire sandbox for that command — dropping filesystem isolation, network filtering, and everything else — just to allow a single IPC call.

Real-world example: 1Password CLI + sandbox

I run Claude Code with the sandbox enabled, using 1Password (op CLI) for credential management. The op CLI communicates with the 1Password desktop app via Mach IPC (XPC) for biometric authentication (Touch ID). The sandbox blocks this:

kernel: (Sandbox) Sandbox: op(43886) deny(1) mach-lookup 2BUA8C4S2C.com.1password.browser-helper

Everything else works — unix sockets are reachable (allowUnixSockets), filesystem access is fine, network is fine. The only thing blocked is one Mach service lookup.

Workarounds I had to implement

To make this work, I had to:

  1. Split credential retrieval and API calls into separate Bash invocationsop read runs unsandboxed (dangerouslyDisableSandbox: true), writes the token to a file, then a second sandboxed Bash call reads the token and makes the API request. This keeps curl sandboxed but adds complexity.
  1. Hardcode /tmp/claude/ for token files$TMPDIR differs between sandboxed (/tmp/claude) and unsandboxed (/var/folders/...) contexts. Token files must use the sandboxed path so both calls can access them.
  1. Add CLAUDE.md instructions telling every session to use dangerouslyDisableSandbox: true for op read — because excludedCommands: ["op"] doesn't reliably bypass Seatbelt (it still blocks the Mach lookup even in a fresh session with the setting confirmed loaded).
  1. Maintain a PreToolUse hook (api-gate.sh) restricting op to op read from a specific vault — since the sandbox can't scope the command, the hook provides the access control layer.

The result works but it's fragile, and the security model is worse than it needs to be: every op read invocation drops the entire sandbox instead of just allowing one Mach service.

What I'd like to see

An allowMachLookup setting, following the same allowlist model as allowUnixSockets:

{
  "sandbox": {
    "allowMachLookup": [
      "2BUA8C4S2C.com.1password.browser-helper"
    ]
  }
}

This would generate a Seatbelt rule like:

(allow mach-lookup (global-name "2BUA8C4S2C.com.1password.browser-helper"))

With this, op read would work inside the sandbox — filesystem isolation, network filtering, and all other restrictions stay active. No need for dangerouslyDisableSandbox, no split Bash calls, no TMPDIR workarounds.

1Password is the most accessible secret management for Claude Code users

1Password is one of the most widely adopted credential management tools — it works for individual developers and scales to small teams sharing vaults. The op CLI with desktop app integration (Touch ID) is arguably the easiest way to give Claude Code secure, human-gated access to API tokens and secrets. It doesn't require infrastructure (no HashiCorp Vault, no self-hosted service), works out of the box on macOS, and the biometric gate means credentials are never auto-dispensed.

The sandbox blocking this specific integration pushes users toward less secure alternatives: hardcoded tokens, env vars in shell profiles, or disabling the sandbox entirely. Supporting op via allowMachLookup would make the recommended secure workflow the path of least resistance.

Broader applicability

This isn't just about 1Password. Other macOS CLI tools use Mach IPC too — security (Keychain access), xcrun (Xcode tools), and anything that communicates with a desktop app via XPC. A generic allowMachLookup setting handles all of these without needing tool-specific workarounds.

Side note: excludedCommands bug

sandbox.excludedCommands is documented to run commands outside the sandbox. With "op" in excludedCommands and a fresh session, op read still fails with the same Mach IPC denial. Verified the setting is loaded via jq '.sandbox.excludedCommands' ~/.claude/settings.json. This may be a separate bug worth looking into.

Environment

  • macOS 26.4, Apple Silicon (M2 Pro)
  • Claude Code 2.1.86
  • 1Password CLI 2.33.1
  • 1Password desktop app with CLI integration enabled

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗