Repository navigation
macOS XProtect kills the Chromium that bun.lock pins, so browse cannot launch #2554
Description
macOS XProtect kills the Chromium that bun.lock pins, so browse cannot launch
gstack version: 1.62.0.0
Platform: macOS 15.5 (Darwin 25.5.0), Apple silicon
What happens
browse fails to launch a browser. macOS XProtect (xprotectd) terminates
chrome-headless-shell on start — the process is killed by the OS, not by
Playwright, so the failure surfaces as a launch timeout rather than anything
naming XProtect.
The binary XProtect objects to is Playwright's Chromium revision 1208:
~/Library/Caches/ms-playwright/chromium_headless_shell-1208/
Not the browse binary itself — that was byte-identical to its 7 May build
throughout, before and after the failure started. Nothing in gstack changed. An
XProtect definition update changed, and revision 1208 fell inside it.
The cause is the committed lockfile, not the semver range
package.json already permits a fix:
"playwright": "^1.58.2"^1.58.2 allows any 1.x at or above 1.58.2, so a fresh resolve would pick up a
newer Chromium on its own. But the committed bun.lock pins it:
"playwright@1.58.2"
"playwright-core@1.58.2"
and browse is compiled with bun build --compile, which bakes the resolved
playwright-core into the binary. So the lockfile — not the declared range —
is what hands every macOS user Chromium 1208.
What fixes it
Bumping to playwright@1.62.1 (Chromium revision 1234) and rebuilding
browse restores it. Playwright pruned 1208 itself on install, so there is no
leftover to clean up.
playwright 1.58.2 → chromium 1208 killed by xprotectd
playwright 1.62.1 → chromium 1234 launches normally
Why this needs fixing upstream rather than locally
The obvious workaround — edit package.json/bun.lock and rebuild — does not
survive. /gstack-upgrade runs git reset --hard origin/main, which reverts
both files and puts browse back on the Chromium that XProtect kills. So every
user who fixes it locally loses the fix at their next upgrade, silently, and the
symptom returns looking like a fresh problem.
And it is not one machine's antivirus being unusual: XProtect is on by default
on every Mac, and the pin is the same for everyone. Anyone on gstack 1.62.0.0
running macOS should be hitting this.
Suggested fix
Refresh bun.lock to a Playwright at or above 1.62.1 and rebuild the shipped
browse binary.
Two things that would make the next occurrence much cheaper to diagnose,
whichever Chromium is current:
- Surface the real cause. A launch failure where the browser process is
killed by the OS currently looks like a generic timeout. Checking
log show --predicate 'process == "xprotectd"'after a launch failure, or
simply naming XProtect as a possibility in the error text, would have saved
the entire investigation here. - Don't let a pin quietly outlive its Chromium. Any pinned browser revision
will eventually land in a definition update. Tracking Playwright more closely,
or documenting how to bump it in a way that survives/gstack-upgrade, stops
this being a recurring silent break.
What I have not verified
Which XProtect definition version introduced it, and whether the detection is a
true positive against something in that Chromium build or a false one. I did not
disable, exclude, or re-run anything against XProtect — the diagnosis is from the
kill itself and from the version bump resolving it.
Activity
v1.64.0.0 fix wave: full tracker audit — 90 fixes, 52 issues closed, …