Chrome XSLT Use-After-Free Exploited in the Wild (CVE-2026-125350)
A use-after-free in Chrome's bundled libxslt can corrupt memory; CVE-2026-125350 is exploited in the wild and fixed in 157.0.8103.50.
TL;DR
- A use-after-free in Chrome's XML and XSLT handling lets a crafted page corrupt renderer memory. Google rates CVE-2026-125350 High and says an exploit exists in the wild.
- Every desktop Chrome release before 157.0.8103.50 is affected. Statcounter puts Chrome at 66.98 percent of desktop browser share worldwide in October 2026.
- CVE-2026-125350 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog as of November 10, 2026.
- The flaw is in libxslt's direct pattern match cache, which Chrome bundles. The same fix closes CVE-2026-125346, reported separately on 2026-10-12.
- Update Chrome to 157.0.8103.50 or 157.0.8103.51, then restart the browser. Chromium-based browsers need their vendor's update. See "How do I fix it?".
Am I affected?
You are exposed when all of these hold:
- You run desktop Google Chrome earlier than 157.0.8103.50 on Windows, macOS or Linux.
- You open a page the attacker controls, or a page that loads attacker-controlled XML and XSLT. No further interaction is needed for the vulnerable parser to run.
- The build does not already carry the libxslt fix. Google shipped it in the 157.0.8103.50 and 157.0.8103.51 desktop releases on 2026-11-09.
The advisory covers desktop Chrome. Chromium-based browsers share the engine, but each vendor ships its own build and its own fix schedule. Check with the vendor before assuming a Chromium browser is patched.
| Branch | Affected versions | Fixed version |
|---|---|---|
| Chrome for Windows and macOS | every release before 157.0.8103.50/.51 | 157.0.8103.50 or 157.0.8103.51 |
| Chrome for Linux | every release before 157.0.8103.50 | 157.0.8103.50 |
Check the installed version from the browser:
# Open this URL in Chrome and read the version line
chrome://version
From a terminal, the package manager reports the installed build:
# Debian and Ubuntu
dpkg-query -W -f='${Version}\n' google-chrome-stable
# Fedora and RHEL
rpm -q google-chrome-stable
# macOS
defaults read "/Applications/Google Chrome.app/Contents/Info.plist" CFBundleShortVersionString
Compare the result with 157.0.8103.50. A build earlier than that number is affected.
How do I fix it?
- Update Chrome to 157.0.8103.50 or later. On Windows and macOS, open the three-dot menu, choose Help, then About Google Chrome, and let the update install. On Linux, update the package:
sudo apt update && sudo apt install --only-upgrade google-chrome-stable - Restart the browser. An update that is downloaded but not applied leaves the old renderer running.
- If you manage Chrome through an enterprise policy, confirm that the update is allowed and that version reporting shows 157.0.8103.50 or later on every endpoint.
- If you use a Chromium-based browser, check its advisory and update channel. Do not assume the Chrome build number applies to it.
- If you cannot update immediately, restrict browsing to trusted sites and block untrusted XML and XSLT content at the proxy. That reduces exposure; it is not a fix.
There is no configuration switch that disables the vulnerable pattern cache while keeping XSLT working. Google's release is the fix.
What is the root cause?
The bug is a re-entrancy flaw in xsltTestCompMatchDirect() in libxslt's pattern matcher. The function caches the node-set produced by a direct pattern evaluation in the transform context's runtime extras, and it reads the cached pointer before it evaluates the pattern.
This is the vulnerable code in third_party/libxslt/src/libxslt/pattern.c, in the Chromium tree before the fix:
list = (xmlXPathObjectPtr)
XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
if ((list == NULL) || (prevdoc != doc)) {
...
newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
...
if (nocache == 0) {
if (list != NULL)
xmlXPathFreeObject(list);
list = newlist;
XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
(void *) list;
...
} else
list = newlist;
}
The cache exists so repeated direct pattern tests on the same document reuse one node-set instead of re-evaluating the XPath for every node. It is keyed on the first step's runtime extras: a list pointer, the document the list was built for, and an index. That design assumes the evaluation does not change the cache. XSLT permits lazy evaluation, so a global variable or a template parameter can run a nested transform instruction while the outer evaluation is still on the stack. The nested xsl:number can prime or replace the same cache slot, which breaks the assumption. The function reads list from the cache before xmlXPathEval. The evaluation can re-enter xsltTestCompMatchDirect() for the same cache slot, for example through a lazily evaluated global variable whose value runs xsl:number. The nested call frees or replaces the cached object. The outer call then frees the stale list pointer, which is now a double free and leaves the cache pointing at freed memory.
The Chromium fix commit describes the same sequence. The cached node-set is read before the evaluation, the nested call may free and replace it, and the outer call then frees it again.
How is it exploited?
The attacker needs a document that Chrome parses as XML with an XSLT stylesheet. The stylesheet drives the pattern matcher into the re-entrant cache path.
- The victim opens a page that loads an attacker-controlled XML document with an
xml-stylesheetprocessing instruction, or an attacker-controlled XSLT stylesheet. - A template match or
xsl:numberpattern uses a construct that is evaluated lazily, such as a global variable whose value runsxsl:number. - The direct pattern match cache is primed for the pattern, then
xmlXPathEvalre-entersxsltTestCompMatchDirect()for the same cache slot. - The nested call frees or replaces the cached node-set. The outer call frees the stale pointer and stores
newlistin its place. - The transform continues with a cache entry that points to freed memory, giving a use-after-free in the renderer.
Google says an exploit for CVE-2026-125350 exists in the wild. It has not published the exploit, the attack chain, the affected sites or the identity of the attackers. The CVE record was not in the public CVE database when this post was written, and Google restricts the bug details while users update.
The same fix closes CVE-2026-125346, a use-after-free in XML reported by Arni Hardarson of Neonix Security on 2026-10-12. Google did not say that one is exploited. The two reports exercise the same cache bug.
How does the attack flow?
A crafted XML and XSLT document drives a re-entrant pattern-cache evaluation. The nested call frees the cached node-set, and the outer call frees it again, leaving the renderer with a use-after-free.
What can an attacker do?
An attacker who triggers the bug corrupts memory in the Chrome renderer. Google rates the flaw High and says an exploit exists in the wild. The company has not said whether the exploit escapes the renderer sandbox, which process it targets, or what it does after code execution.
The conditions are part of the impact:
- The attacker needs the victim to load attacker-controlled XML or XSLT. A normal page visit is enough.
- The vulnerable code runs in the renderer. Code execution there is bounded by Chrome's sandbox until a second flaw or a sandbox escape is chained. Chrome sandboxes the renderer on every desktop platform. The exploit Google reports may stop at the renderer or be part of a larger chain, and the public record does not say which. A renderer memory-corruption primitive is the first stage of most browser exploit chains, so the update is urgent either way.
- No public exploit code is available. The in-the-wild exploit is known from Google's statement, not from a published sample.
Do not read "exploited in the wild" as "full device compromise". Google has not published that chain, and the renderer sandbox is a separate boundary.
Why does the fix work?
The fix re-reads the cache slot after xmlXPathEval, so the outer call frees the object that is in the cache now, not the pointer it read before the nested call. This is the added code from Chromium commit 61cab3f77203:
@@ -581,6 +581,15 @@ xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
nocache = 1;
if (nocache == 0) {
+ /*
+ * xmlXPathEval can re-enter this function for the same cache
+ * slot, e.g. through a lazily evaluated global variable whose
+ * value runs xsl:number. The nested call may free or replace
+ * the cached object, so re-read it instead of using the value
+ * read before the evaluation.
+ */
+ list = (xmlXPathObjectPtr)
+ XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
if (list != NULL)
xmlXPathFreeObject(list);
list = newlist;
The fix is complete for the Chromium copy. It closes both CVE-2026-125350 and CVE-2026-125346, and the commit adds a regression test that loads the crafted XSLT in an iframe.
The upstream libxslt project has not taken the change. The libxslt/pattern.c file on the upstream master branch still reads list before xmlXPathEval and frees it after the call. Chromium carries the fix as a patch in third_party/libxslt/chromium. Software that embeds libxslt, including server-side XML pipelines and other browsers, should ask its vendor whether that copy is patched.
How do I check if I was compromised?
Google has published no indicators of compromise for CVE-2026-125350. A browser exploit leaves little on disk, so the reliable check is to confirm the browser version and treat any period on an affected build as exposure.
- Confirm that every desktop Chrome install runs 157.0.8103.50 or later. Use
chrome://versionlocally and your endpoint management inventory for the rest. - Review browser crash reports from the affected period for renderer crashes on pages that load XML or XSLT. A crash is a lead, not proof of exploitation.
- Review proxy and DNS logs for XML or XSLT content from hosts your users do not normally visit. Google has published no domains or hashes.
- If you suspect exploitation, preserve the browser profile, crash dumps and proxy logs before wiping the machine, then rebuild it.
An exploit that succeeds may leave no crash and no file. The absence of a crash does not prove that a host was not exposed.
Timeline
- 2026-10-12: Arni Hardarson of Neonix Security reports CVE-2026-125346, a use-after-free in XML.
- 2026-11-06: an anonymous researcher reports CVE-2026-125350, a use-after-free in XML that Google later says is exploited in the wild.
- 2026-11-07: Chromium lands commit
61cab3f77203, which fixes both bugs in the libxslt direct pattern match cache. - 2026-11-09: Google releases Chrome 157.0.8103.50/.51 for Windows and macOS and 157.0.8103.50 for Linux.
FAQ
Is CVE-2026-125350 exploited in the wild?
Yes. Google's stable-channel post says it is aware that an exploit for CVE-2026-125350 exists in the wild. Google has not said who is using it, which sites serve it, or whether it escapes the renderer sandbox.
Is there a public exploit?
No. Google has not published exploit code, and the CVE record was not public when this post was written. The in-the-wild exploit is known from Google's statement, not from a sample.
Does this affect Chrome on Android?
Google's advisory covers the desktop stable channel. It does not list Chrome for Android. Treat Android as unconfirmed rather than safe, and keep it updated through the Play Store.
Are other Chromium browsers affected?
Probably, until their vendors ship the same libxslt fix. Chrome's build number does not apply to Edge, Brave, Opera or Vivaldi. Check each vendor's advisory and update channel.
What is the direct pattern match cache?
It is a per-transform cache in libxslt that stores the node-set produced by a direct XPath pattern evaluation. It avoids re-evaluating the same pattern for every node. Because the cache lives in the transform context, a nested evaluation can reach the same slot and replace the stored object.
Is libxslt itself fixed?
No. The upstream libxslt master branch still has the vulnerable read, and Chromium carries the fix as a local patch. Applications that embed libxslt should track the upstream project and their vendor.
How urgent is the update?
Update now. The flaw is reachable from a normal page visit, Chrome is the majority desktop browser, and Google says an exploit exists. The update takes a restart.
References
- Chrome Releases, "Stable Channel Update for Desktop", 2026-11-09, the fixed versions, the nine security fixes, CVE-2026-125350, CVE-2026-125346 and the in-the-wild statement: https://chromereleases.googleblog.com/2026/11/stable-channel-update-for-desktop_018223192.html (checked November 10, 2026)
- Chromium commit 61cab3f77203671e09402e68738aa217632aed8d, "Fix use-after-free in libxslt direct pattern match cache", the fix and the regression test: https://github.com/chromium/chromium/commit/61cab3f77203671e09402e68738aa217632aed8d (checked November 10, 2026)
- The vulnerable
xsltTestCompMatchDirect()inthird_party/libxslt/src/libxslt/pattern.cbefore the fix: https://github.com/chromium/chromium/blob/6eade082d6e5/third_party/libxslt/src/libxslt/pattern.c (checked November 10, 2026) - Upstream libxslt
libxslt/pattern.con the master branch, still carrying the pre-fix sequence: https://github.com/GNOME/libxslt/blob/master/libxslt/pattern.c (checked November 10, 2026) - Statcounter Global Stats, desktop browser market share worldwide, October 2026: https://gs.statcounter.com/browser-market-share/desktop/worldwide (checked November 10, 2026)
- CISA Known Exploited Vulnerabilities catalog JSON feed, checked for CVE-2026-125350 on November 10, 2026 (not listed): https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (checked November 10, 2026)