Chrome XML zero-day CVE-2026-125350: patch headless too

Chrome XML zero-day CVE-2026-125350 is fixed in 157.0.8103.50. Auto-update skips headless Chrome in Playwright, Puppeteer and Docker. How to check yours.

Terminal session beside the takeaway: Chrome fixed an exploited XML bug. Headless copies stay behind. Desktop Chrome updates itself. Check the browser inside Playwright, Puppeteer and Docker against 157.0.8103.50.
Quick summary · TL;DR
  1. Check the browser version inside your containers, not on your laptop. Only the desktop install updates itself. Headless copies stay behind, and the build they need is Chrome 157.0.8103.50, which Google shipped on 9 November 2026 to fix CVE-2026-125350, a use after free in XML with an exploit in the wild.
  2. Puppeteer's latest release still ships a Chrome without the fix. v25.17.0, out on 10 November, rolled to 157.0.8103.38, a build below 157.0.8103.50. Install 157.0.8103.50 with @puppeteer/browsers and point executablePath at it.
  3. Playwright's bundled Chromium can't be called patched or unpatched yet. v1.65.0 ships Chromium 158.0.8127.18 from the Beta branch and Google hasn't said whether that build has the fix. Running channel: 'chrome' on an updated Chrome is the safe route.
  4. Extended Stable users want 156.0.8078.96. That build carries the same fix on Windows and Mac.

Desktop Chrome updates itself to the fix for the Chrome zero-day CVE-2026-125350. The headless copy inside your Playwright install, Puppeteer cache or Docker image doesn’t. Google patched this use after free in XML, which has an exploit in the wild, in Stable 157.0.8103.50 on 9 November 2026, so any Chrome that loads other people’s pages needs its version checked today.

What Google patched for the Chrome zero-day CVE-2026-125350

Google’s Stable Channel Update for Desktop (9 November 2026) moves Stable to 157.0.8103.50/.51 on Windows and Mac and 157.0.8103.50 on Linux. Rollout runs over the coming days and weeks. Of the 9 security fixes it carries, two are High-severity use-after-free bugs in XML:

  • CVE-2026-125350, reported anonymously on 6 November 2026. Google wrote that it “is aware that an exploit for CVE-2026-125350 exists in the wild.”
  • CVE-2026-125346, reported on 12 October 2026 by Arni Hardarson of Neonix Security.

Bug details stay restricted until most users have updated, so Google hasn’t said which XML code is affected or how the exploit is delivered.

Extended Stable moved to 156.0.8078.96 on Windows and Mac the same day, with the CVE-2026-125350 fix included. Chrome for Android 157.0.8103.50 also shipped on 9 November, though its post only mentions stability and performance.

Timeline

Date (2026)What happened
12 OctCVE-2026-125346 reported to Google
22 OctPuppeteer v25.16.0 released, default browser Chrome 156.0.8078.47
5 NovPlaywright v1.65.0 released, bundled Chromium 158.0.8127.18
6 NovCVE-2026-125350 reported, anonymously
9 NovStable 157.0.8103.50, Extended Stable 156.0.8078.96, Android 157.0.8103.50
9 Nov, 22:11 UTCChrome for Testing lists Stable as 157.0.8103.50, with chromedriver and chrome-headless-shell builds
10 Nov, 14:02 UTCPuppeteer v25.17.0 released, default browser Chrome 157.0.8103.38

Why the Chrome zero-day CVE-2026-125350 fix skips your scraping fleet

Your laptop’s browser has an updater. A headless fleet usually runs a browser that something else downloaded and pinned:

Where the browser comes fromWhy it stays oldWhat closes the gap
Playwright (npx playwright install)Fetches the Chromium build its release nameschannel: 'chrome', or the next release
Puppeteer cacheDownloads the Chrome version its release names@puppeteer/browsers install of 157.0.8103.50 plus executablePath
Docker imagesKeep the browser from build dayRebuild without the layer cache
CI jobs and crawlersPin Chrome for Testing or chromedriver on purposeBump the pin to 157.0.8103.50

None of those move when Google ships a fix. That hurts most on a scraping or QA fleet, since it loads untrusted pages all day and that is exactly the input a browser exploit needs. Running the fleet behind residential proxies or any other exit doesn’t change that. A proxy changes the IP the target sees. Your browser still parses whatever the page sends back.

Puppeteer: the latest release is still below the fix

The newest Puppeteer release, v25.17.0, came out on 10 November 2026 and rolled to Chrome 157.0.8103.38. That’s a Chrome 157 build, but an earlier one than 157.0.8103.50, and Google lists the fix in .50, so .38 isn’t on the fixed list. The release before it, v25.16.0 (22 October 2026), defaulted to 156.0.8078.47. Updating Puppeteer alone won’t close the gap today.

So for now, install a patched build yourself and point Puppeteer at it:

npx @puppeteer/browsers install chrome@157.0.8103.50
# or the headless shell
npx @puppeteer/browsers install chrome-headless-shell@157.0.8103.50

Each command prints the install path. Pass it as executablePath in puppeteer.launch() or set PUPPETEER_EXECUTABLE_PATH. The Puppeteer proxy guide covers the launch options if your proxy flags live there too.

Playwright: can’t be confirmed either way

Playwright v1.65.0 (5 November 2026) bundles Chromium 158.0.8127.18, a build from the Chrome 158 Beta branch, which is also what Chrome for Testing lists as Beta. Google’s posts don’t say whether that build includes the CVE-2026-125350 fix, and the bug is restricted.

If you’d rather not guess, run Playwright against branded Chrome you know is current. npx playwright install chrome puts branded Google Chrome in your operating system’s default location. It replaces any Chrome already installed there. Launch with channel: 'chrome' after that. The Playwright proxy guide shows where channel sits next to your proxy settings.

Check what your fleet actually runs

Ask the binary inside the container, not the host:

google-chrome --version
chrome-headless-shell --version

Or ask the running browser. In Puppeteer, await browser.version() returns something like HeadlessChrome/157.0.8103.50. In Playwright, browser.version() returns the bare number.

To compare against the build that fixes the Chrome zero-day CVE-2026-125350 in a shell (GNU sort -V):

v=$(google-chrome --version | grep -oE '[0-9]+(\.[0-9]+){3}')
min=157.0.8103.50
[ "$(printf '%s\n' "$min" "$v" | sort -V | head -n1)" = "$min" ] && echo "ok $v" || echo "update $v"

On Extended Stable the line to beat is 156.0.8078.96 instead, so set min to that. A Chromium build with a different number, like Playwright’s 158 Beta build, can’t be judged by this check.

Keep the sandbox on while you patch

Until the patched build is everywhere, Chromium’s sandbox limits what a renderer bug can reach. Two common setups switch it off:

  • Playwright’s chromiumSandbox launch option “Defaults to false”, per the BrowserType launch docs. Set chromiumSandbox: true in scripts that open pages you don’t control.
  • Playwright’s official Docker image runs browsers as root, which disables the sandbox. For crawling, the docs recommend a separate user plus their seccomp_profile.json.

If a sandboxed launch fails, fix the user or the seccomp profile. Adding --no-sandbox just turns the protection off.

What to do now

  • List every place a browser comes from. Lockfiles, Dockerfiles, CI caches and the PUPPETEER_EXECUTABLE_PATH or executablePath values in your code.
  • Patch what you control. Pull 157.0.8103.50 from Chrome for Testing, update branded Chrome, and rebuild images instead of trusting the cache.
  • Limit exposure in the meantime. Keep headless sessions short-lived and away from secrets they don’t need. The scraping architecture guide has the worker layout this fits into.

Frequently asked questions

It's a High-severity use after free in Chrome's XML handling, reported anonymously on 6 November 2026. Google said on 9 November that it is aware an exploit exists in the wild. Details are restricted until most users update.

Stable 157.0.8103.50 on Linux and 157.0.8103.50/.51 on Windows and Mac, released 9 November 2026. On Extended Stable the fix is in 156.0.8078.96 for Windows and Mac. Chrome for Testing lists 157.0.8103.50 with chromedriver and chrome-headless-shell builds.

Its default browser is. Puppeteer v25.17.0, released on 10 November 2026, rolled to Chrome 157.0.8103.38, still below the fixed 157.0.8103.50. The release before it, v25.16.0, defaulted to 156.0.8078.47. Your workaround is to install chrome@157.0.8103.50 with npx @puppeteer/browsers and pass its path as executablePath, or to use channel: 'chrome' once the system Chrome is updated.

Nobody outside Google can say yet. Playwright v1.65.0 bundles Chromium 158.0.8127.18, a Beta-branch build, and Google's posts don't say whether it includes the fix. Running Playwright with channel: 'chrome' on an updated Google Chrome avoids the question.

Run google-chrome --version or chrome-headless-shell --version inside the container, or call browser.version() from Puppeteer or Playwright. Compare the four-part number with 157.0.8103.50, or 156.0.8078.96 on Extended Stable.

Usually not. Playwright and Puppeteer download their own builds, Docker images keep the browser they were built with, and pinned Chrome for Testing versions stay pinned. Updating or rebuilding them is a manual job.

Chrome for Android 157.0.8103.50 shipped on 9 November 2026. Its release post only mentions stability and performance and doesn't list CVE-2026-125350, so check Google's desktop post for the security details.

Researched and drafted with AI tools, then checked against our publishing rules before it went live: 7 outside links, 4 links to other proxymint pages, no prices and a fact-check pass against our product records. How we write.