//nefariousplan

CVE-2026-125350: Chrome's XML UAF KEV Lands Two PoCs Within Twelve Hours. One Flags Patched Users Vulnerable. The Other Describes A Chrome From February 2025.

patterns

cve

proof of concept

CVE-2026-125350 is a use-after-free in Chrome's XML component. Google patched it on November 9, 2026, in Stable 157.0.8103.50/.51 and Extended Stable 156.0.8078.96, credited an anonymous reporter who filed three days earlier, and attached a sentence to the release note that does not appear next to any other CVE in the update: Google is aware that an exploit for CVE-2026-125350 exists in the wild. CISA added the identifier to the Known Exploited Vulnerabilities catalog on November 10 with a federal civilian remediation deadline of November 24. Two GitHub repositories whose names contain the string CVE-2026-125350 were published within twelve hours of the KEV listing. One of them tells a user on patched Extended Stable that their browser is vulnerable. The other names an affected-versions range that ends before Chrome 134, which Google shipped in February 2025.

What Google shipped on November 9

The Chrome Stable Channel Update for Desktop that landed at 12:52 PT on November 9, 2026 announced 157.0.8103.50/.51 for Windows and Mac and 157.0.8103.50 for Linux, with nine security fixes. The Extended Stable Update seven minutes earlier announced 156.0.8078.96 with eleven security fixes. The Android release followed at 15:00 PT with Chrome 157. Four of the Stable fixes and eleven of the Extended Stable fixes include the same CVE identifiers; CVE-2026-125350 is one of them.

Two of the fixes in the Stable release are tagged Use after free in XML:

[TBD][ 572578603 ] High CVE-2026-125346: Use after free in XML.
  Reported by Arni Hardarson (Neonix Security) on 2026-10-12
[N/A][ 582442907 ] High CVE-2026-125350: Use after free in XML.
  Reported by anonymous on 2026-11-06

Both Chromium bug IDs are restricted. The release note's standard prefix applies: Access to bug details and links may be kept restricted until a majority of users are updated with a fix. The restriction holds for crbug 582442907 as of this writing. Nobody outside Google and the anonymous reporter can read the bug.

One sentence in the release note is attached to the second CVE and not the first:

Google is aware that an exploit for CVE-2026-125350 exists in the wild.

This is the Disclosure After Exploitation shape in a Chromium-specific form. The anonymous attribution and the in-the-wild line together establish that the report arrived from somebody watching exploitation happen, not from a named researcher claiming credit. Three days between the anonymous report and the Stable release. One day between the Stable release and the CISA KEV addition. Twelve hours between the CISA KEV addition and the two public repositories whose names contain the string CVE-2026-125350. The anonymous reporter wrote working exploit bytes that Google used to produce the patch. Neither of the two public authors wrote anything that reaches the parser.

ashrafzaryouh/CVE-2026-125350 is a version checker that misses Extended Stable

ashrafzaryouh/CVE-2026-125350 is one file, CVE-2026-125350.html, 5,845 bytes, first commit at 14:54 UTC on November 10. The commit graph shows four edits over twenty-eight minutes by Ashraf Zaryouh <[email protected]>. The HTML renders a card with a header CVE-2026-125350 under a subtitle labelling it the Chrome XML Use-After-Free Safe Status Checker, and a footer:

This tool only reads the browser version string. No XML is parsed, no memory operations, no exploit code.

The script reads navigator.userAgentData.getHighEntropyValues(['fullVersionList']) (with a navigator.userAgent regex fallback), parses the Chrome version into a four-element integer array, and compares it against a hardcoded constant:

const FIXED = [157, 0, 8103, 50];

function isPatched(ver) {
  if (!ver) return false;
  for (let i = 0; i < 4; i++) {
    if (ver[i] > FIXED[i]) return true;
    if (ver[i] < FIXED[i]) return false;
  }
  return true; // equal is patched
}

The constant matches the Stable Channel version Google announced on November 9. It does not match the Extended Stable Channel version Google announced seven minutes before it. A user whose browser reports 156.0.8078.96 is tested against FIXED[0] = 157, the first iteration fails ver[0] < FIXED[0], and isPatched returns false. The checker labels the user VULNERABLE and tells them to update:

Your browser version is vulnerable. Update Chrome immediately to 157.0.8103.50 or later and restart the browser.

Chrome Extended Stable is the release channel enterprise operators configure when they want security fixes without feature-change churn. The November 9 Extended Stable update includes CVE-2026-125350. A security team that rolled 156.0.8078.96 to its managed fleet on November 10 and then ran the checker, searching for reassurance before the KEV deadline, is told its patched fleet is unpatched. The thing the checker names as the fixed version is one of two fixed versions. The thing the checker tells the user to do, update to 157, is not an option on the channel they are running. The author read the Stable Channel Update post and did not scroll up to the Extended Stable Update post sitting above it.

The HTML does nothing an existing browser-accessible page does not already do. chrome://settings/help shows the user their Chrome version and whether an update is available, authoritatively, without a CVE-named GitHub repository in the loop. The thing the checker adds to that workflow is a CVE identifier on the badge and a hardcoded version comparison that gets the Extended Stable case wrong.

Frostmoon39206/CVE-2026-125350-PoC is a placeholder with two different proton inboxes

Frostmoon39206/CVE-2026-125350-PoC is five tracked paths at HEAD: README.md, exploit.py, requirements.txt, LICENSE, and screenshots/poc.png. The commit graph shows eight commits in a seventeen-minute window starting at 21:34 UTC on November 10 by Frostmoon39206 <[email protected]>, with the committer identity renamed to DeFrost mid-session against the same email. The first three commits dropped exploit.py and requirements.txt into a screenshots/ subdirectory by accident; the author deleted them and re-uploaded them at the tree root.

The README's Affected Versions section:

## Affected Versions
* Google Chrome < 134.0.6998.45
* Chromium-based browsers (Microsoft Edge, Brave, Opera) < equivalent builds
*(Note: Verified on Chrome 133.0.6943.126 and 134.0.6998.35 on Linux)*

Google shipped Chrome 134.0.6998.45 in February 2025. The anonymous CVE-2026-125350 report landed in November 2026 against a Chrome Stable branch twenty-three majors downstream of it. The three version numbers in the README (134.0.6998.45, 133.0.6943.126, 134.0.6998.35) are all from Chrome's early-2025 release window; none of them have any operational relationship to the bug the repository's name identifies. The README names a vulnerability window that closed twenty months before the anonymous reporter filed.

exploit.py is 76 lines. The function the CLI runs on --generate:

def generate_xml_payload():
    """
    Generates the base XML structure required to reach the vulnerable parser.
    The malicious UAF trigger is intentionally omitted in this public version.
    """
    print("[*] Generating base XML structure (skeleton)...")

    # Standard XML template used to reach the parser state
    xml_template = """<?xml version="1.0" encoding="UTF-8"?>
<root>
    <node id="target">
        <data>fuzz_input_here</data>
        <payload>
            <!-- UAF trigger logic removed from public repo -->
        </payload>
    </node>
</root>"""

    # TODO: Implement heap grooming and UAF trigger logic here.
    # This requires precise object alignment and memory manipulation,
    # which is restricted to the commercial version.

    print("[+] Base XML generated. Trigger logic disabled.")
    return xml_template

The template is nine lines of inert XML and one HTML comment admitting the trigger is absent. The TODO comment below the return value names exactly the primitive the CVE describes and explicitly states it is not present. requirements.txt declares requests>=2.31.0 and lxml>=4.9.3; exploit.py imports neither. The dependencies are decoration for the template. This is the Placeholder PoC pattern in its canonical form: a tracked exploit script whose own source names the gap between what the script does and what the CVE describes.

The README's sales section:

Access & Terms

The public code in this repository is intentionally restricted and non-functional to prevent automated abuse by scanners.

If you are a pentester, red teamer, or vulnerability researcher looking to acquire the full, weaponized Proof-of-Concept, contact for private access:[email protected]

Please include your intended use case and target environment. Commercial licensing terms are available upon request.

The exploit.py module docstring advertises a different address:

"""
CVE-2026-125350 / EUVD-2026-121390
Google Chrome XML Use-After-Free (CWE-416)

*** SKELETON ONLY ***
This script is a non-weaponized proof-of-concept.
It generates the base XML structure required to reach the parser,
but DOES NOT contain the heap grooming or UAF trigger required for RCE.

For access to the full weaponized pipeline, contact: [email protected]
"""

The README's sales contact is [email protected]. The exploit.py's sales contact is [email protected]. One of the two is the author's intended sales channel. The other is a template string the author did not search-and-replace. The buyer cannot tell which. The seller does not need to decide; the seller needs one proton inbox to receive mail from whoever thinks the KEV deadline is worth trying both. This is the Paywall PoC pattern: the README is a storefront, the repository tree is the storefront's facade, and the product is what the buyer believes about the bytes at the moment of payment.

screenshots/poc.png is the storefront's advertisement. It is a 32 KB terminal-screenshot composite showing claimed output of the private version:

[*] Target: https://█████████
[*] Sending crafted XML payload...
[*] Triggering UAF...
[+] Memory corruption successful.
[+] Arbitrary read/write achieved.
[*] Executing command: id
uid=1000(chrome) gid=1000(chrome) groups=1000(chrome),4(adm),24(cdrom)

The target URL is blurred. The output is text. The hostname (render-node-01) and kernel string (Linux render-node-01 6.1.0-13-amd64 ... Debian 6.1.55-1 (2026-10-28)) are plausible but unverifiable. Nothing in the image is a reproducible artifact. The screenshot is marketing. The seller does not need a working exploit to render it; the seller needs a terminal and a screenshot tool. Everything the image testifies to is a claim the buyer evaluates after they pay [email protected] or [email protected] or both.

The anonymous reporter has the primitive

Both XML use-after-frees Chrome fixed on November 9 are restricted in the Chromium issue tracker. crbug 572578603 (CVE-2026-125346) is [TBD]; crbug 582442907 (CVE-2026-125350) is [N/A]. Chrome's bug restriction clause covers both: details and links remain withheld until a majority of users are updated. The two researchers who found the bugs made different attribution choices. Arni Hardarson of Neonix Security put their name on CVE-2026-125346, reported on October 12. The reporter of CVE-2026-125350, filed on November 6, chose anonymity. Google's in-the-wild acknowledgement attaches to the second, not the first.

Neither researcher published a PoC. Chromium's bug tracker is the only public surface the primitive would appear on, and both tickets are restricted. The vulnerability-intelligence pipeline that polls GitHub for CVE-2026-125350-named repositories registered the two repositories above as PoC available; the bug the scanner graded a 10 on is sealed inside a locked issue tracker that neither author has read. The anonymous reporter has the primitive. Google has the primitive. The two GitHub authors have an identifier, a template, and a KEV deadline to price against.

This is the second time in five months this blog has covered the same shape against a Chrome KEV bug. The June 23 federal civilian deadline for CVE-2026-11645, a V8 out-of-bounds read and write, arrived with three CVE-named repositories on GitHub: a tab-crasher, a Spanish-language chatbot transcript containing uncompilable JavaScript, and a TinyURL redirecting to a payment platform. The three repositories collectively performed zero out-of-bounds reads and zero out-of-bounds writes. They registered identically on the pipeline that counts CVE-named repositories as weaponization evidence. Today's two CVE-2026-125350 repositories are the smaller, faster version of the same workflow. The economic shape of Paywall PoC does not depend on the bug class. It depends on the KEV deadline and the scanner's willingness to count repository names.

The playbook has been written. Run git ls-tree -r HEAD before treating any CVE-named repository as evidence of a public PoC. Compare the README's affected-versions table against the vendor's release blog. Resolve every outbound contact in a sales section before scoring the artifact. The two repositories above fail at the tree-listing layer; the Frostmoon39206 repository additionally fails at the version-table layer, the file-imports layer, the dependency-manifest layer, and the sales-contact-consistency layer. Reading the two files is the review. Neither needs to be opened in a sandbox, and neither needs to be reverse-engineered.

The scanner that polls GitHub for CVE-2026-125350 logged gh-search+2 and did not open the files. The vulnerability intelligence pipeline that consumed that signal added multi-poc×2+1 for the second repository. The federal civilian SOC analyst searching GitHub for a PoC to validate their detection posture before November 24 finds the version checker and the skeleton, in that order of upload. The checker does not help them. The skeleton tells them to email a proton inbox.

PoCs: ashrafzaryouh/CVE-2026-125350, Frostmoon39206/CVE-2026-125350-PoC.

Chrome's release blog named the fix on November 9. The anonymous reporter had the primitive. The two authors who published on November 10 had the identifier, a template, and twelve hours.