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

Uninitialized Use in ANGLE in Google Chrome prior to 149

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

This is a peephole in Chrome’s graphics plumbing, not a battering ram through the front door

CVE-2026-10994 is an *uninitialized use* bug in Chrome’s ANGLE graphics layer, meaning a malicious page can potentially coax the browser into exposing stale process memory that should never be surfaced to web content. The affected range is Chrome before 149.0.7827.53; Google’s desktop stable notes show fixes in 149.0.7827.53 for Linux and 149.0.7827.53/.54 for Windows and macOS.

Google’s MEDIUM / 6.5 rating is basically fair. The bug is remotely triggerable and Chrome is everywhere, but the real-world attack still needs a user to open attacker-controlled content, the impact is *information disclosure rather than code execution*, and the threat telemetry is cold: no KEV listing, no vendor note of in-the-wild exploitation, and an EPSS of 0.00035.

"Remote and real, but this is a user-driven browser info leak with no public exploitation signal"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land the victim on a malicious page

The attacker uses a phishing link, malvertising, or a compromised site to get a user onto attacker-controlled HTML/JavaScript. The weapon is just a crafted web page; no auth or local foothold is required.
Conditions required:
  • Victim uses vulnerable Chrome
  • Victim opens attacker-controlled or attacker-influenced content
  • Normal web browsing is allowed
Where this breaks in practice:
  • Requires user interaction (UI:R)
  • Email gateway, web filtering, or safe browsing controls may stop delivery
  • Attack dies if the browser already updated itself
Detection/coverage: Traditional vuln scanners do not see this from the network; detection is mainly browser version inventory, web proxy telemetry, and phishing controls.
STEP 02

Exercise the ANGLE rendering path

The page has to drive Chrome into the vulnerable ANGLE code path, likely via graphics-heavy browser features such as WebGL/canvas rendering. The attacker needs a reliable trigger that causes uninitialized memory to become observable inside the renderer process.
Conditions required:
  • ANGLE-backed rendering path is reachable on the target platform
  • Attacker knows how to trigger the buggy code path
  • Chrome mitigation behavior does not fully mask the leak
Where this breaks in practice:
  • Bug details are still restricted in Google’s release notes
  • Browser memory-corruption primitives are notoriously finicky across GPU/driver/platform combinations
  • Enterprise GPU settings, rendering differences, and browser hardening reduce exploit reliability
Detection/coverage: EDR rarely labels this step cleanly; browser crash telemetry and GPU-process instability may be the only weak signal.
STEP 03

Turn stale memory into usable disclosure

If the primitive works, the attacker reads back memory that was never initialized correctly and tries to extract tokens, fragments, pointers, or other sensitive process data. The practical weapon is a custom JavaScript harness that repeatedly triggers and samples the leak.
Conditions required:
  • Leaked bytes are attacker-observable
  • Useful secrets happen to be resident in reachable memory
  • Leak quality is high enough to separate signal from noise
Where this breaks in practice:
  • Information leaks are often noisy and low-precision
  • Chrome site isolation and process boundaries sharply reduce the odds of getting high-value cross-origin secrets in one shot
  • Many leaks are only useful when chained with another bug
Detection/coverage: Almost no signature-based coverage; this is better caught by version management than by exploit detection.
STEP 04

Exfiltrate the data

Any recovered bytes can be posted back over ordinary HTTPS from the attacker page. That gives the attacker whatever small slice of memory they managed to harvest, but not automatic code execution or privilege gain by itself.
Conditions required:
  • Victim browser can make outbound web requests
  • The attacker successfully parsed valuable data from the leak
Where this breaks in practice:
  • DLP is weak against small encrypted web beacons but the actual amount of useful data may be tiny
  • The leak may produce nothing actionable on most runs
Detection/coverage: Network controls usually see only normal HTTPS from a browser; practical coverage is low unless the destination domain is already blocked.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo current exploitation signal found. CISA KEV does not list CVE-2026-10994, and Google’s stable release note does not include the usual language used when it knows of active exploitation.
Public PoC availabilityNo public PoC found in browsed sources as of 2026-06-05. Google explicitly says bug details may stay restricted until most users are patched, which is normal for fresh Chrome memory-safety fixes.
EPSS0.00035 from supplied intel; that is effectively background noise, not an exploitation wave. Percentile was not available in the authoritative browsed sources.
KEV statusNot KEV-listed as checked against CISA’s Known Exploited Vulnerabilities Catalog on 2026-06-05.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N = remote reachability, no auth, but user interaction required and confidentiality-only impact.
Affected versionsChrome prior to 149.0.7827.53. Google’s desktop stable bulletin maps the fixed builds to 149.0.7827.53 (Linux) and 149.0.7827.53/.54 (Windows/macOS).
Fixed versionsUpgrade to 149.0.7827.53+ on Linux and 149.0.7827.53/.54+ on Windows/macOS. I found no distro-specific Chromium backport evidence in browsed sources, so treat vendor Chrome versioning as authoritative here.
Exposure realityShodan/Censys-style internet counts are the wrong lens. This is a client-side browser issue, so exposure is your endpoint fleet size, not a server listening on the internet.
Disclosure timelineThere is a date mismatch worth noting: Google shipped the fixed desktop stable build on 2026-06-02, the early stable build was visible on 2026-05-29, and third-party/public alerting appeared on 2026-06-05. Your supplied CVE intel lists 2026-06-04 as disclosure.
ReporterReported by Mufeed VH from Winfunc Research on 2026-04-21, per Google’s Chrome stable release note.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to MEDIUM (5.2/10)

The decisive factor is that this is a user-driven confidentiality leak, not a pre-auth internet-facing server compromise or an RCE. Chrome’s huge footprint keeps it relevant, but the absence of exploitation evidence and the need to convert a fragile renderer leak into useful data keep it squarely in the middle bucket.

HIGH Affected version range and fixed build identification
MEDIUM Real-world exploitability without restricted bug details
HIGH Assessment that no active exploitation signal is presently visible

Why this verdict

  • User interaction drags it down: the attacker must get a victim onto malicious content, which implies phishing/malvertising success rather than straight unauthenticated exploitation of an exposed service.
  • The impact is leak-only: the vendor vector is confidentiality-only with no integrity or availability loss, so this is not the kind of bug that independently takes over endpoints.
  • Threat intel is cold: no KEV, no public PoC found, and EPSS at 0.00035 all argue against urgent exploitation pressure.
  • Browser ubiquity keeps it from falling to LOW: Chrome is everywhere in enterprise fleets, and browsers routinely hold session material and sensitive page data, so even a mere info leak deserves patch coverage.

Why not higher?

There is no present evidence of broad in-the-wild use, and the bug does not hand the attacker code execution on its own. In practice, an ANGLE memory-disclosure primitive still has to survive browser mitigations, platform variance, and the problem of turning leaked bytes into something valuable.

Why not lower?

This is still a remote web-triggered browser bug in a massively deployed product. Even when the standalone impact is limited to disclosure, browsers sit next to SSO sessions, internal apps, and sensitive content, so dismissing it as backlog-only would be too relaxed.

05 · Compensating Control

What to do — in priority order.

  1. Enforce Chrome auto-update — Make sure enterprise policy, MDM, or endpoint tooling is not pinning users below the fixed build. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but because Chrome updates are low-friction this should ride your normal desktop update control immediately.
  2. Audit version pinning and deferred channels — Find OUs, rings, VDI images, kiosk builds, and exception groups stuck on older Chrome milestones. There is no mitigation SLA — go straight to the 365-day remediation window, and this check is how you keep one stale ring from quietly carrying the risk for months.
  3. Keep browser and GPU sandboxing intact — Do not relax Chrome hardening or renderer isolation to work around application issues unless you absolutely must. There is no mitigation SLA — go straight to the 365-day remediation window, and intact sandboxing is your best damage-limiter if a browser info leak is ever chained.
  4. Use web filtering against newly seen domains — This will not fix the bug, but it does reduce the chance of victims reaching attacker-controlled pages that try to exercise it. There is no mitigation SLA — go straight to the 365-day remediation window; treat this as exposure reduction, not a substitute for the fixed build.
What doesn't work
  • A WAF does not materially help because the attack executes in the *client browser* after the user loads malicious content.
  • MFA does not stop the vulnerability from leaking renderer memory; it only reduces the value of some stolen session artifacts.
  • External network vuln scanning is mostly useless here because there is no server-side service banner to probe; you need endpoint/browser inventory instead.
06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or through your EDR/RMM agent. Invoke it as python3 check_chrome_cve_2026_10994.py on macOS/Linux or py check_chrome_cve_2026_10994.py on Windows; no administrator rights are normally required, though Windows registry access to machine-wide install keys must be allowed.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_chrome_cve_2026_10994.py
# Determine whether a local Google Chrome installation is vulnerable to CVE-2026-10994.
# Fixed baseline used here: 149.0.7827.53 (Linux) and 149.0.7827.53/.54 (Windows/macOS).
# Any version < 149.0.7827.53 is treated as VULNERABLE.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

import os
import platform
import re
import shutil
import subprocess
import sys

FIXED = (149, 0, 7827, 53)
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')


def parse_version(text):
    if not text:
        return None
    m = VERSION_RE.search(text)
    if not m:
        return None
    return tuple(int(x) for x in m.groups())


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


def read_cmd(path):
    try:
        out = subprocess.check_output([path, '--version'], stderr=subprocess.STDOUT, text=True, timeout=5)
        return out.strip()
    except Exception:
        return None


def check_windows_registry():
    versions = []
    try:
        import winreg  # type: ignore
    except Exception:
        return versions

    roots = [
        (winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Google\Chrome\BLBeacon'),
        (winreg.HKEY_CURRENT_USER, r'SOFTWARE\Google\Chrome\BLBeacon'),
        (winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\WOW6432Node\Google\Chrome\BLBeacon'),
    ]

    for hive, keypath in roots:
        try:
            with winreg.OpenKey(hive, keypath) as k:
                val, _ = winreg.QueryValueEx(k, 'version')
                v = parse_version(str(val))
                if v:
                    versions.append((keypath, v))
        except Exception:
            pass
    return versions


def check_windows_files():
    candidates = [
        os.path.join(os.environ.get('ProgramFiles', r'C:\Program Files'), 'Google', 'Chrome', 'Application', 'chrome.exe'),
        os.path.join(os.environ.get('ProgramFiles(x86)', r'C:\Program Files (x86)'), 'Google', 'Chrome', 'Application', 'chrome.exe'),
        os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Google', 'Chrome', 'Application', 'chrome.exe'),
    ]
    versions = []
    for path in candidates:
        if path and os.path.exists(path):
            out = read_cmd(path)
            v = parse_version(out)
            if v:
                versions.append((path, v))
    return versions


def check_macos():
    candidates = [
        '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
        os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
    ]
    versions = []
    for path in candidates:
        if os.path.exists(path):
            out = read_cmd(path)
            v = parse_version(out)
            if v:
                versions.append((path, v))
    return versions


def check_linux():
    names = ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser']
    versions = []
    for name in names:
        path = shutil.which(name)
        if path:
            out = read_cmd(path)
            v = parse_version(out)
            if v:
                versions.append((path, v))
    return versions


def fmt(v):
    return '.'.join(str(x) for x in v)


def main():
    system = platform.system().lower()
    found = []

    if system == 'windows':
        found.extend(check_windows_registry())
        found.extend(check_windows_files())
    elif system == 'darwin':
        found.extend(check_macos())
    elif system == 'linux':
        found.extend(check_linux())
    else:
        print(f'UNKNOWN - Unsupported platform: {platform.system()}')
        sys.exit(2)

    # De-duplicate by (location, version)
    uniq = []
    seen = set()
    for item in found:
        if item not in seen:
            uniq.append(item)
            seen.add(item)
    found = uniq

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

    vulnerable = []
    patched = []
    for loc, ver in found:
        if cmp_ver(ver, FIXED) < 0:
            vulnerable.append((loc, ver))
        else:
            patched.append((loc, ver))

    if vulnerable:
        print('VULNERABLE - Found browser version(s) below 149.0.7827.53:')
        for loc, ver in vulnerable:
            print(f'  {loc}: {fmt(ver)}')
        if patched:
            print('Also found patched version(s):')
            for loc, ver in patched:
                print(f'  {loc}: {fmt(ver)}')
        sys.exit(1)

    print('PATCHED - All discovered browser version(s) are >= 149.0.7827.53:')
    for loc, ver in patched:
        print(f'  {loc}: {fmt(ver)}')
    sys.exit(0)


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

If you remember one thing.

TL;DR
Monday morning, treat this as fleet patch hygiene, not incident response. For a MEDIUM reassessment there is noisgate mitigation SLA: no mitigation SLA — go straight to the 365-day remediation window; for noisgate remediation SLA, get your Chrome estate onto 149.0.7827.53+ through the normal browser-update channel and use endpoint inventory to smoke out pinned or deferred rings that missed auto-update. If you already run Chrome auto-update well, this should close quickly without a special fire drill.

Sources

  1. Google Chrome Releases - Stable Channel Update for Desktop (Chrome 149)
  2. Google Chrome Releases - Early Stable Updates
  3. VulDB entry for CVE-2026-10994
  4. CISA Known Exploited Vulnerabilities Catalog
  5. FIRST EPSS API documentation
  6. FIRST EPSS model overview
  7. GovCERT.HK alert for Chrome 149 vulnerabilities
  8. Chrome Enterprise release channel guidance
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.