← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-10989 · CWE-122 · Disclosed 2026-06-04

Inappropriate implementation in V8 in Google Chrome prior to 149

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

This is a booby-trapped webpage that still needs the victim to grab the right handle before it springs

CVE-2026-10989 is a V8 memory-safety flaw in Google Chrome that affects versions before 149.0.7827.53 on Linux and before 149.0.7827.53/54 on Windows and macOS. The public description says a remote attacker must get a user onto a crafted HTML page and then convince them to perform *specific UI gestures* before heap corruption is reachable, which is materially narrower than a plain drive-by browser bug.

Google labeled it HIGH at 8.8, and that is fair as a worst-case technical baseline for a browser memory corruption issue. In enterprise reality, though, the chain is narrower: it is client-side, requires user interaction, requires *specific* gestures beyond a click, has no public in-the-wild evidence, no KEV listing, and no public exploit chain showing sandbox escape or reliable post-compromise impact, so the vendor number overstates operational urgency for fleet patch prioritization.

"Real bug, but it needs user interaction plus specific gestures and stays in the browser lane unless chained."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land the victim on attacker content

Weaponized tool: phishing link, malvertising redirect, or a compromised site serving a crafted HTML page. The attacker does not hit your Chrome fleet directly; they must win browser traffic and user attention first.
Conditions required:
  • User browses to attacker-controlled or attacker-influenced web content
  • Enterprise filtering does not block the domain or redirect chain
Where this breaks in practice:
  • Secure Web Gateway, DNS filtering, browser isolation, and ad blocking kill a lot of this before V8 is ever reached
  • Unlike server-side CVEs, there is no unauthenticated service to scan and hit at will
Detection/coverage: Network and URL telemetry usually sees the lure stage well; vulnerability scanners do not see exploit delivery, only browser version drift.
STEP 02

Trigger the V8 bug with scripted page logic

Weaponized tool: custom JavaScript heap-grooming and DOM/event logic targeting V8 behavior. The page must not just render; it must maneuver the victim into the specific UI gesture path described in the advisory to reach the faulty implementation.
Conditions required:
  • Victim uses an affected Chrome version
  • Targeted code path is reachable in that browser build
  • The victim performs the required gesture sequence
Where this breaks in practice:
  • UI:R already narrows reliability, and the advisory's specific UI gestures language narrows it again
  • Exploit reliability for modern Chrome V8 bugs is non-trivial because of hardening, allocator behavior, and version churn
Detection/coverage: EDR rarely labels this CVE specifically; browser crash telemetry and suspicious renderer crashes are better signals than signature-based IDS.
STEP 03

Corrupt memory inside the browser process

Weaponized tool: the exploit transitions from logic bug to heap corruption in V8. At this point the attacker is still typically fighting for code execution or controlled corruption inside Chrome's sandboxed renderer context, not instant domain compromise.
Conditions required:
  • Exploit primitives are reliable on the victim's exact version/build
  • Mitigations such as CFG, sandboxing, and memory-safety hardening do not break the chain
Where this breaks in practice:
  • Many browser exploits crash more often than they achieve stable execution across mixed fleet versions
  • Enterprise desktops are heterogeneous enough that reliability falls off fast
Detection/coverage: Crash spikes, abnormal child-process behavior, and browser exploit prevention telemetry may surface this stage; Nessus/Qualys-type coverage is version-only.
STEP 04

Attempt post-renderer impact or chaining

Weaponized tool: secondary exploit or a follow-on credential/session theft play. Without a separate sandbox escape, OS-level persistence, or a useful data-theft path in-browser, the blast radius is often limited to the browser session and what that user can reach there.
Conditions required:
  • Attacker obtains meaningful code execution or a useful same-user session outcome
  • A second bug or business-context objective exists
Where this breaks in practice:
  • No public evidence here of a companion sandbox escape or active exploit chain
  • Browser isolation, EDR, and rapid auto-update reduce dwell time even if initial corruption works
Detection/coverage: Post-exploit activity is where EDR has the best chance: abnormal process trees, browser child spawning, token theft behavior, or suspicious network egress.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public evidence of active exploitation located; not present in CISA KEV as of this assessment (CISA KEV).
Proof-of-concept availabilityNo public PoC or exploit repository was found in the sources reviewed; Chromium issue is still access-restricted (issue 516311623).
EPSS0.00035 from the supplied intel, which is extremely low and consistent with low near-term mass exploitation probability; percentile was not authoritatively surfaced in the reviewed sources.
KEV statusNo KEV listing found; therefore no CISA evidence-backed exploitation date or federal due date applies (KEV catalog).
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = remote and no auth, but user interaction is mandatory and scope is unchanged (NVD).
Affected versionsChrome before 149.0.7827.53 on Linux and before 149.0.7827.53/54 on Windows/macOS (Google Chrome Releases, NVD).
Fixed versionsUpgrade to 149.0.7827.53 on Linux and 149.0.7827.53/54 on Windows/macOS. This is an evergreen browser fix, not a distro-style backport story in the referenced advisories.
Scanning / exposure dataInternet exposure counts from Shodan/Censys/FOFA are not operationally useful here because this is a client-side browser bug, not a network service. The actionable signal is endpoint software inventory and browser version compliance, not external attack-surface scanning.
Disclosure timelineChrome published the stable release on 2026-06-02; NVD shows the CVE record received on 2026-06-04 and published on 2026-06-04 (Google, NVD).
ReporterReported by Google on 2026-05-25 in the Chrome release notes entry for CVE-2026-10989 (Chrome release note line item).
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (6.2/10)

The decisive factor is the prerequisite chain: this is a browser client bug that needs the victim to reach attacker content and perform *specific UI gestures*, which sharply reduces reach and reliability versus a clean drive-by RCE. With no KEV listing, no public exploitation evidence, and no public chain to sandbox escape, this belongs below the vendor's generic browser-memory-corruption baseline.

HIGH Affected versions and fixed versions
MEDIUM Real-world exploitability and fleet urgency

Why this verdict

  • Vendor baseline starts at 8.8, but that assumes technical impact in a vacuum; I start there because Chrome is ubiquitous and V8 bugs can be serious.
  • UI:R is real downward pressure; the attacker cannot simply hit a listening service, they need a human in the loop on a crafted page.
  • The advisory says specific UI gestures, not just a click; that is another explicit friction point, so I subtract again for exploit reach and reliability.
  • This is post-content-delivery, not internet-exposed infrastructure; you cannot mass-scan enterprises for it the way you can VPN, edge, or server CVEs.
  • No KEV and no public active exploitation mean there is no evidence-backed urgency override.
  • No public sandbox-escape chain in the reviewed sources limits confidence in worst-case endpoint compromise from this CVE alone.

Why not higher?

If this were being exploited in the wild, KEV-listed, or described as a straight drive-by renderer RCE with no extra gesture requirement, it would stay in HIGH. Chrome/V8 memory bugs deserve respect, but this record publicly describes a narrower user-driven path and does not show the kind of chaining evidence that justifies emergency fleet disruption.

Why not lower?

This is still a remotely delivered browser memory-corruption issue in a massively deployed product, not harmless noise. If an attacker can reliably steer users into the required interaction path, the potential impact on browser confidentiality, integrity, and availability is meaningful enough that backlog-only treatment would be too relaxed.

05 · Compensating Control

What to do — in priority order.

  1. Enforce auto-update compliance — Make sure Chrome stable-channel auto-update is enabled and that version drift is visible in your endpoint inventory. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but evergreen browser drift should still be corrected in the next normal software-compliance cycle.
  2. Reduce untrusted web exposure — Apply or tighten Secure Web Gateway, DNS filtering, browser isolation, and ad/malvertising controls for high-risk user groups. These controls cut off the attacker before the crafted page reaches V8; for MEDIUM, use them as risk reduction while completing patching inside the 365-day remediation window.
  3. Hunt for stale Chrome builds — Query your fleet for Chrome versions below 149.0.7827.53 (149.0.7827.54 on some Windows/macOS channels) and focus first on unmanaged endpoints, kiosks, VDI gold images, and systems with disabled updates. The practical problem here is not exposure on the internet; it is update drift on endpoints.
  4. Monitor browser crash anomalies — Watch EDR, MDM, or browser telemetry for spikes in Chrome renderer crashes and suspicious child-process behavior after visits to untrusted sites. This does not prevent exploitation, but it is one of the few realistic ways to catch a live attempt in user space.
What doesn't work
  • Perimeter vulnerability scanning doesn't meaningfully reduce risk here because there is no exposed server-side service to fingerprint and attack.
  • MFA helps with account protection but does nothing to stop a memory-corruption trigger in the local browser engine.
  • WAF rules are irrelevant for most enterprise users because the exploit is delivered to the browser as client content, not blocked at your app edge unless you control the destination site.
  • User training alone is too weak here; specific UI gestures is a friction point, but social engineering and lure pages can still get users there.
06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or via your EDR/MDM remote execution channel. Invoke it with python3 check_chrome_cve_2026_10989.py on Windows, macOS, or Linux; no admin rights are usually needed if Chrome is installed in standard locations, but broader file-system search works better with local read access.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_chrome_cve_2026_10989.py
# Determine whether local Google Chrome version is vulnerable to CVE-2026-10989.
# Outputs one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

import os
import platform
import re
import shutil
import subprocess
import sys
from typing import Optional, Tuple

FIXED_LINUX = (149, 0, 7827, 53)
FIXED_WIN_MAC_MIN = (149, 0, 7827, 53)  # some channels show 53, some 54; 53 is the minimum fixed build family


def parse_version(text: str) -> Optional[Tuple[int, int, int, int]]:
    m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', text)
    if not m:
        return None
    return tuple(int(x) for x in m.groups())


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 p.returncode, out.strip()
    except Exception:
        return 999, ''


def check_binary(path: str) -> Optional[Tuple[int, int, int, int]]:
    if not path or not os.path.exists(path):
        return None
    rc, out = run_cmd([path, '--version'])
    if rc in (0, 1):
        v = parse_version(out)
        if v:
            return v
    return None


def get_version_windows() -> Optional[Tuple[int, int, int, int]]:
    candidates = [
        os.path.expandvars(r'%ProgramFiles%\Google\Chrome\Application\chrome.exe'),
        os.path.expandvars(r'%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'),
        os.path.expandvars(r'%LocalAppData%\Google\Chrome\Application\chrome.exe'),
    ]
    for c in candidates:
        v = check_binary(c)
        if v:
            return v
    return None


def get_version_macos() -> Optional[Tuple[int, int, int, int]]:
    candidates = [
        '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
        os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
    ]
    for c in candidates:
        v = check_binary(c)
        if v:
            return v
    return None


def get_version_linux() -> Optional[Tuple[int, int, int, int]]:
    names = ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser']
    for name in names:
        path = shutil.which(name)
        if path:
            v = check_binary(path)
            if v:
                return v
    return None


def compare(v1, v2):
    return (v1 > v2) - (v1 < v2)


def main():
    system = platform.system().lower()
    version = None
    fixed = FIXED_WIN_MAC_MIN

    if 'windows' in system:
        version = get_version_windows()
        fixed = FIXED_WIN_MAC_MIN
    elif 'darwin' in system or 'mac' in system:
        version = get_version_macos()
        fixed = FIXED_WIN_MAC_MIN
    elif 'linux' in system:
        version = get_version_linux()
        fixed = FIXED_LINUX
    else:
        print('UNKNOWN: unsupported operating system')
        sys.exit(2)

    if not version:
        print('UNKNOWN: Chrome/Chromium version not found')
        sys.exit(2)

    if compare(version, fixed) < 0:
        print(f'VULNERABLE: detected version {".".join(map(str, version))} is below fixed {".".join(map(str, fixed))}')
        sys.exit(1)
    else:
        print(f'PATCHED: detected version {".".join(map(str, version))} is at or above fixed {".".join(map(str, fixed))}')
        sys.exit(0)


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

If you remember one thing.

TL;DR
Monday morning: do not treat this like an edge-device fire drill. Put it into your normal Chrome evergreen compliance workflow, query for endpoints below 149.0.7827.53 / 149.0.7827.54, fix update drift on unmanaged systems, kiosks, and VDI images, and validate that auto-update is actually landing. For a MEDIUM verdict there is noisgate mitigation SLA here — no mitigation SLA — go straight to the 365-day remediation window — and the noisgate remediation SLA is ≤365 days; because this is a browser, most mature teams should still clear it far sooner through their standard browser ring deployment rather than letting it age all year.

Sources

  1. Google Chrome Releases - Stable Channel Update for Desktop
  2. NVD - CVE-2026-10989
  3. CVE Record - CVE-2026-10989
  4. Chromium issue 516311623
  5. Canadian Centre for Cyber Security advisory AV26-544
  6. CISA Known Exploited Vulnerabilities Catalog
  7. VulDB entry for CVE-2026-10989
  8. Chromium Security page
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.