← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-9126 · CWE-416 · Disclosed 2026-05-20

Use after free in DOM in Google Chrome on prior to 148

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a burglar who gets into the lobby, not the building vault

CVE-2026-9126 is a CWE-416 use-after-free in Chrome's DOM handling that can be triggered by a crafted HTML page. Google shipped the fix on 2026-05-19 in Chrome 148.0.7778.178/179 for Windows/Mac and 148.0.7778.178 for Linux; Debian backports show the Linux/Chromium fix at 148.0.7778.178-1. The important technical limiter is in the description itself: successful exploitation gives the attacker code execution inside the renderer sandbox, not direct OS-level code execution.

The vendor-style 8.8 HIGH overstates the operational urgency for enterprise patch scheduling. In the real world this requires a user to hit attacker content, the reachable population is broad but not externally enumerable like a server bug, and the payoff from this CVE alone is bounded by Chrome's sandbox unless the attacker also has a second bug for sandbox escape or post-exploitation abuse within the browser context. Google's own release note classified it as Medium, and that aligns better with defender reality than the raw CVSS label.

"Real bug, but not a drop-everything fire: it needs user action and only lands inside Chrome's sandbox"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land the victim on attacker-controlled web content

The attacker needs the user to render a malicious HTML page, typically via phishing, malvertising, a compromised site, or an in-app browser view. The practical weapon here is just a hostile webpage or ad payload; no exposed service is needed because the browser is the target surface.
Conditions required:
  • Victim is running a vulnerable Chrome/Chromium build
  • User visits attacker-controlled or attacker-influenced content
  • Browser protections do not block the page before render
Where this breaks in practice:
  • Requires user interaction (UI:R)
  • Email gateways, web filtering, Safe Browsing, ad blocking, and browser isolation can break delivery
  • Enterprises with managed browser restarts may already have the fixed build
Detection/coverage: Server-side vuln scanners are weak here. Coverage comes mainly from asset/version inventory, EDR browser telemetry, secure web gateway logs, and phishing telemetry.
STEP 02

Trigger the DOM use-after-free in the renderer

A crafted HTML/JavaScript sequence exercises the DOM bug and corrupts renderer memory. The exploit objective at this stage is renderer-process control, typically via a custom in-browser exploit chain; no public PoC was located in current GitHub/Exploit-DB style searches, and the Chromium bug is still access-restricted.
Conditions required:
  • Attacker can execute active web content in the victim browser
  • Target build is below the fixed version
  • Exploit is reliable against the target platform/build
Where this breaks in practice:
  • Memory-corruption browser exploits are fragile across versions and platforms
  • No broadly public exploit code was found
  • Issue details are restricted until patch uptake improves
Detection/coverage: Network signatures are poor. Browser crash spikes, renderer process anomalies, exploit mitigation alerts, and EDR detections for abnormal child-process behavior are more realistic.
STEP 03

Execute code inside Chrome's sandbox

If the exploit lands, the attacker gets arbitrary code execution inside the sandboxed renderer context. That can still be useful for same-origin data theft, session abuse, credential phishing overlays, or staging a follow-on exploit, but it is not the same as direct host takeover.
Conditions required:
  • Renderer compromise succeeded
  • Attacker's goals are achievable from sandboxed browser context or a second bug is available
Where this breaks in practice:
  • Chrome sandbox meaningfully limits filesystem, process, and OS access
  • Site Isolation and origin boundaries constrain blast radius
  • Many enterprise detections trigger only when the attacker tries to move beyond browser context
Detection/coverage: EDR may not see the initial memory bug but can often catch breakout attempts, suspicious browser child processes, token theft attempts, or abnormal persistence actions.
STEP 04

Chain to meaningful host impact

To turn this into workstation compromise, the attacker normally needs a sandbox escape, a local privilege escalation, or a browser-to-native handoff bug. That second-stage requirement is the main reason this is not a top-tier patch emergency on its own.
Conditions required:
  • Attacker has a separate sandbox escape or post-browser path
  • Defender controls do not stop the follow-on stage
Where this breaks in practice:
  • Requires an additional exploit or abuse path beyond CVE-2026-9126
  • EDR, application control, OS hardening, and privilege boundaries raise failure rates
  • No in-the-wild evidence was found tying this CVE to active chained exploitation
Detection/coverage: Detection improves sharply at this step: EDR, application control, LPE detections, and browser-to-OS telemetry are relevant.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo evidence found of active exploitation. CISA KEV does not list CVE-2026-9126, and CISA-ADP SSVC data surfaced via CIRCL shows Exploitation: none.
Proof-of-concept availability*Inference from current search results:* no public PoC/exploit repository was located in common GitHub/Exploit-DB style searches, and the linked Chromium issue remains access-restricted.
EPSSUser-supplied EPSS is 0.0003; Snyk currently shows 0.03% (9th percentile) for Debian's mapped record, which is consistent with a very low near-term exploitation signal.
KEV statusNot KEV-listed. No CISA KEV due date applies.
CVSS vector meaningCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H says internet-deliverable and easy to trigger once delivered, but it also explicitly requires user interaction and does not model the practical limiter that impact is confined to the browser sandbox.
Affected versionsUpstream advisory says Chrome before 148.0.7778.179. Google's release note is more precise: fixed in 148.0.7778.178/179 for Windows/Mac and 148.0.7778.178 for Linux.
Fixed versionsGoogle Chrome: 148.0.7778.179 on Windows/Mac, 148.0.7778.178 on Linux. Debian Chromium backports: 148.0.7778.178-1~deb12u1 for bookworm-security and 148.0.7778.178-1~deb13u1 for trixie-security.
Scanning / exposure reality*Inference:* Shodan/Censys/FOFA/GreyNoise are a poor fit because this is endpoint browser software, not an internet-listening server. Exposure equals your managed browser fleet and unmanaged endpoints, not a queryable external attack surface.
Disclosure timelineDisclosed 2026-05-20; Google shipped the relevant stable desktop update on 2026-05-19 and public CVE/NVD records appeared on 2026-05-20.
Reporter / provenanceGoogle's release note attributes the underlying Chromium issue (496280532) to Google, reported on 2026-03-25.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (6.5/10)

The decisive factor is that this bug lands inside Chrome's sandbox, not on the host, so meaningful workstation compromise usually requires a second exploit. That sharply cuts real-world impact compared with what the raw 8.8 CVSS implies, especially with no KEV listing, no active exploitation evidence, and no public PoC surfaced.

HIGH Affected and fixed version mapping
MEDIUM Real-world exploitability without a public exploit chain
HIGH Downgrade rationale driven by sandbox-only impact

Why this verdict

  • Downgrade for sandbox-only payoff: the CVE description itself says code execution is *inside a sandbox*; that is materially less dangerous than direct endpoint RCE.
  • Downgrade for user interaction: UI:R means the attacker needs the victim to hit malicious content first, so this is not wormable or self-propagating across the estate.
  • Downgrade for missing threat signal: no KEV listing, no active exploitation evidence found, and no public PoC surfaced in current searches reduce immediate patch pressure.
  • Small upward adjustment for ubiquity: Chrome is everywhere, so once delivery happens the reachable population can be large even though the exploit still needs user action.
  • Downward pressure from enterprise controls: safe browsing, SWG filtering, browser isolation, EDR, managed auto-update, and restart enforcement all interrupt different parts of the chain.

Why not higher?

This is not a server-side RCE and not a host-level browser escape by itself. The attacker must first get a user onto malicious content, then successfully exploit a fragile memory bug, and then still deal with Chrome's sandbox to reach meaningful OS impact.

Why not lower?

It is still a real memory-corruption bug in a massively deployed client application exposed to untrusted internet content all day. If an attacker can reliably trigger it at scale, sandboxed execution can still enable browser-context abuse and serve as the first half of a more serious chain.

05 · Compensating Control

What to do — in priority order.

  1. Enforce browser auto-update and restart compliance — Make Chrome/Chromium restart compliance visible in your endpoint tooling so patched binaries are actually loaded. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but in practice browsers should move in your normal evergreen cycle rather than sit half-patched for months.
  2. Route high-risk web traffic through browser isolation or hardened VDI — Use remote browser isolation, disposable VDI, or equivalent controls for users who routinely open external links, ads, or unknown web content. There is no mitigation SLA for a MEDIUM rating, so apply this as a risk-reduction measure where you already have the capability while remediating within 365 days.
  3. Block unmanaged or out-of-date browsers — Use conditional access, EDR posture checks, or proxy controls to deny access from stale Chrome builds and unmanaged Chromium forks. This keeps the exposed population from drifting upward while you close the issue inside the 365-day remediation window.
  4. Preserve Chrome sandbox and site isolation settings — Do not weaken browser sandboxing, renderer isolation, or related hardening flags in enterprise policy unless there is a tested business requirement. Those controls are exactly what keep this bug from being an immediate host-compromise emergency.
What doesn't work
  • Perimeter vulnerability scans do not meaningfully measure this risk, because the vulnerable surface is an endpoint browser, not an exposed network service.
  • A WAF does not solve this for general browsing; the exploit is delivered to clients from arbitrary web content, ads, or compromised sites outside your app perimeter.
  • Email filtering alone is insufficient because users can reach malicious pages through messaging apps, documents, search results, ads, or compromised legitimate sites.
06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or via your software inventory/remote execution tooling. Invoke it with python3 check_chrome_cve_2026_9126.py on macOS/Linux or py check_chrome_cve_2026_9126.py on Windows; no admin rights are required, though some install paths may be easier to read with standard user access to the local filesystem and registry.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_chrome_cve_2026_9126.py
# Detect local Chrome/Chromium version exposure for CVE-2026-9126.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

import os
import platform
import re
import subprocess
import sys

APP_NAMES = [
    "Google Chrome",
    "Google Chrome for Testing",
    "Chromium",
    "chrome",
    "chromium",
]


def parse_version(text):
    if not text:
        return None
    m = re.search(r"(\d+)\.(\d+)\.(\d+)\.(\d+)", text)
    if not m:
        return None
    return tuple(int(x) for x in m.groups())


def version_to_str(v):
    return ".".join(str(x) for x in v) if v else "UNKNOWN"


def cmp_ver(a, b):
    return (a > b) - (a < b)


def run_cmd(cmd):
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
        out = (p.stdout or "") + "\n" + (p.stderr or "")
        return out.strip()
    except Exception:
        return ""


def detect_windows():
    candidates = []
    local = os.environ.get("LOCALAPPDATA", "")
    pf = os.environ.get("ProgramFiles", "")
    pf86 = os.environ.get("ProgramFiles(x86)", "")
    paths = [
        os.path.join(local, "Google", "Chrome", "Application", "chrome.exe"),
        os.path.join(pf, "Google", "Chrome", "Application", "chrome.exe"),
        os.path.join(pf86, "Google", "Chrome", "Application", "chrome.exe"),
        os.path.join(local, "Chromium", "Application", "chrome.exe"),
    ]

    try:
        import winreg
        reg_paths = [
            (winreg.HKEY_CURRENT_USER, r"Software\Google\Chrome\BLBeacon"),
            (winreg.HKEY_LOCAL_MACHINE, r"Software\Google\Chrome\BLBeacon"),
            (winreg.HKEY_LOCAL_MACHINE, r"Software\WOW6432Node\Google\Chrome\BLBeacon"),
            (winreg.HKEY_CURRENT_USER, r"Software\Chromium\BLBeacon"),
            (winreg.HKEY_LOCAL_MACHINE, r"Software\Chromium\BLBeacon"),
        ]
        for hive, keypath in reg_paths:
            try:
                key = winreg.OpenKey(hive, keypath)
                version, _ = winreg.QueryValueEx(key, "version")
                if version:
                    candidates.append(("registry", version))
            except OSError:
                pass
    except Exception:
        pass

    for p in paths:
        if os.path.exists(p):
            out = run_cmd([p, "--version"])
            if out:
                candidates.append((p, out))

    return candidates


def detect_macos():
    candidates = []
    apps = [
        "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
        os.path.expanduser("~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
        "/Applications/Chromium.app/Contents/MacOS/Chromium",
    ]
    for p in apps:
        if os.path.exists(p):
            out = run_cmd([p, "--version"])
            if out:
                candidates.append((p, out))
    return candidates


def detect_linux():
    candidates = []
    cmds = [
        ["google-chrome", "--version"],
        ["google-chrome-stable", "--version"],
        ["chromium", "--version"],
        ["chromium-browser", "--version"],
    ]
    for cmd in cmds:
        out = run_cmd(cmd)
        if out:
            candidates.append((" ".join(cmd), out))

    # Debian dpkg fallback
    out = run_cmd(["dpkg-query", "-W", "-f=${Version}", "chromium"])
    if out:
        candidates.append(("dpkg chromium", out))
    return candidates


def main():
    system = platform.system().lower()
    fixed_default = (148, 0, 7778, 179)
    fixed_linux = (148, 0, 7778, 178)

    if "windows" in system:
        fixed = fixed_default
        candidates = detect_windows()
    elif "darwin" in system:
        fixed = fixed_default
        candidates = detect_macos()
    elif "linux" in system:
        fixed = fixed_linux
        candidates = detect_linux()
    else:
        print("UNKNOWN - unsupported platform: {}".format(platform.system()))
        sys.exit(2)

    if not candidates:
        print("UNKNOWN - Chrome/Chromium not found")
        sys.exit(2)

    found_versions = []
    for source, raw in candidates:
        v = parse_version(raw)
        if v:
            found_versions.append((source, raw, v))

    if not found_versions:
        print("UNKNOWN - version could not be parsed from detected installations")
        sys.exit(2)

    # Use the lowest detected version to be conservative.
    lowest = min(found_versions, key=lambda x: x[2])
    source, raw, ver = lowest

    if cmp_ver(ver, fixed) < 0:
        print("VULNERABLE - detected {} from {} ; fixed threshold is {}".format(version_to_str(ver), source, version_to_str(fixed)))
        sys.exit(1)
    else:
        print("PATCHED - detected {} from {} ; fixed threshold is {}".format(version_to_str(ver), source, version_to_str(fixed)))
        sys.exit(0)


if __name__ == "__main__":
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as a managed-browser rollout item, not an all-hands incident. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window; in practice you should verify which endpoints are still below Chrome 148.0.7778.179 on Windows/Mac or 148.0.7778.178 on Linux, sweep unmanaged browsers out of the environment, and fold the actual browser update into your normal evergreen channel with completion inside the noisgate remediation SLA of ≤365 days.

Sources

  1. Google Chrome Releases - Stable Channel Update for Desktop (2026-05-19)
  2. NVD - CVE-2026-9126
  3. Chromium Issue 496280532
  4. Debian Security Tracker - CVE-2026-9126
  5. Snyk Debian 14 mapping for CVE-2026-9126
  6. CISA Known Exploited Vulnerabilities Catalog
  7. CIRCL Vulnerability Lookup - CVE-2026-9126
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.