[BUG] macOS sandbox blocks Chromium/Playwright launch: bootstrap_check_in denied — no mach-register allowance exists, allowMachLookup cannot help
Summary
Headless Chromium (Playwright, Puppeteer, anything Chromium-based) cannot launch inside the macOS Bash sandbox. Chromium's multi-process launch registers a per-pid Mach bootstrap service so its children can rendezvous with the parent; bootstrap_check_in is a mach-register operation, the Seatbelt profile is deny-by-default, and no setting can allow it: the profile contains no mach-register rule at all, and sandbox.network.allowMachLookup — whose schema docs mention Playwright — only ever emits (allow mach-lookup …) rules.
Error
[FATAL:base/apple/mach_port_rendezvous_mac.cc:159] Check failed: kr == KERN_SUCCESS. bootstrap_check_in org.chromium.Chromium.MachPortRendezvousServer.98874: Permission denied (1100)
The process is then force-killed and Playwright fails with TargetClosedError: BrowserType.launch: Target page, context or browser has been closed.
Root cause
sandbox-runtime's macOS profile (src/sandbox/macos-sandbox-utils.ts) allows a fixed list of mach-lookup names ("based on Chrome sandbox policy") plus user-specified allowMachLookup entries, but grepping the profile shows no mach-register allowance anywhere. Under (deny default), any process that must register a new bootstrap service name — Chromium's MachPortRendezvousServer.<pid>, crashpad's child_port_handshake — dies at launch. So allowMachLookup fixes the lookup class of failure (e.g. Go TLS needing trustd, #29533) but structurally cannot fix this one.
Reproduction
Inside a sandboxed Bash call on macOS, with Playwright + chromium installed:
python -c "from playwright.sync_api import sync_playwright; p = sync_playwright().start(); p.chromium.launch(headless=True)"
Workarounds (both fully unsandbox the command)
sandbox.excludedCommandsmatching the specific scriptdangerouslyDisableSandbox: trueper call (unavailable whenallowUnsandboxedCommands: false)
Neither preserves filesystem/network isolation for the browser process, which is the part one actually wants sandboxed.
Suggested fix
A scoped registration allowance mirroring allowMachLookup, e.g.:
"sandbox": { "network": { "allowMachRegister": ["org.chromium.*"] } }
emitting (allow mach-register (global-name-prefix "org.chromium.")), so browser automation can run with the rest of the sandbox intact.
Prior reports
- #14881 — identical failure (
bootstrap_check_in … Permission denied (1100)from puppeteer/crashpad), auto-closed as stale with "please file a new issue and reference this one". - #29533 — the mach-lookup flavor of the same deny-default (Go TLS / trustd); addressed by
enableWeakerNetworkIsolation/allowMachLookup, which cannot address registration.
Environment
- macOS Darwin 25.5.0 (arm64)
- Claude Code 2.1.220, sandbox enabled,
allowUnsandboxedCommands: false - Playwright (Python) with chromium_headless_shell-1228
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗