Skip to content

macOS XProtect kills the Chromium that bun.lock pins, so browse cannot launch #2554

Closed

Description

@pleasantplumbers

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:

  1. 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.
  2. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions