This is the second lock on the vault door, not the front gate
CVE-2026-10889 is an out-of-bounds read in Chrome's ANGLE graphics layer affecting Chrome versions before 149.0.7827.53 on Linux, 149.0.7827.53/54 on Windows and macOS, with corresponding fixes also carried into Android 149.0.7827.59 and Extended Stable 148.0.7778.254 for Windows/macOS. The key detail is the exploitation model in your intel: the attacker must already have *compromised the renderer process* and then use this ANGLE bug to push beyond that boundary.
Vendor-style scoring overstates the fleet risk for defenders because it treats the bug's end-state impact more than its real-world prerequisite chain. In practice this is a *chain component* for a browser sandbox escape path: dangerous for targeted exploitation and red-team quality chains, but sharply constrained by the need for a separate renderer compromise first, the absence of KEV listing, the very low EPSS, and no visible public PoC for this specific CVE.
4 steps from start to impact.
Land malicious browser content
- Victim browses attacker-controlled content
- Chrome/Chromium build is older than the fixed version
- ANGLE code path is reachable on the target platform
- This CVE is not described as a standalone renderer RCE
- Enterprise browsers often auto-update on short cycles
- GPU feature variation can make trigger reliability platform-specific
Obtain renderer compromise first
- Attacker has a distinct renderer exploit
- That exploit works on the victim's exact Chrome build and platform
- User interaction or visit flow reaches the exploit content
- Requires a second bug, not included in this CVE
- Modern Chrome hardening, sandboxing, and site isolation raise chain complexity
- Exploit reliability must survive version drift across a large enterprise fleet
Pivot from renderer into ANGLE/GPU attack surface
- Renderer foothold already exists
- Target uses the vulnerable ANGLE code path
- IPC and rendering path reach the flawed memory access
- ANGLE/GPU paths differ by OS, driver, and hardware
- Some enterprise environments reduce or virtualize GPU acceleration behavior
- Out-of-bounds read is weaker than a write/use-after-free primitive
Leak memory or assist a sandbox escape chain
- Bug is triggerable reliably after renderer compromise
- Leaked memory is useful for the broader chain
- Attacker can convert disclosure into meaningful post-sandbox gain
- Read-only primitive is less directly powerful than a write primitive
- Additional chain work is typically required for stable host compromise
- No evidence this CVE alone is being used at scale
- A WAF or perimeter IPS does not materially help; this is client-side browser attack surface, not a server endpoint you can shield at the edge.
- MFA is irrelevant to exploitability; it protects accounts, not the browser memory-safety path being abused.
- Restarting Chrome without updating does not fix anything except transient state; the vulnerable code remains present until the patched build is installed.
The supporting signals.
| In-the-wild status | No evidence found that CVE-2026-10889 is exploited in the wild as of 2026-06-04; it is not in the CISA KEV catalog. |
|---|---|
| PoC availability | No public PoC or weaponized exploit specific to this CVE was found. The Chromium issue reference exists, but details remain restricted in the Chrome release bulletin. |
| EPSS | Provided EPSS is 0.00068 (~0.068%), which is extremely low and consistent with a narrow, chain-dependent client-side bug rather than a broadly weaponized internet service flaw. Reference: FIRST EPSS and daily data/statistics. |
| KEV status | Not KEV-listed. That matters here because Chrome sandbox-escape-class bugs that are *actually* being used often get rapid ecosystem attention and, when confirmed, KEV treatment. |
| CVSS vector reality check | Provided vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H assumes a network-reachable client-side chain with scope change and full impact. The big real-world dampener is the hidden prerequisite: attacker already controls the renderer. |
| Affected versions | Chrome prior to 149.0.7827.53; desktop stable bulletin lists fixed builds as Linux 149.0.7827.53 and Windows/macOS 149.0.7827.53/54. |
| Fixed versions | Desktop stable fix shipped 2026-06-02 in Chrome 149 stable. Android inherited the same security fixes in 149.0.7827.59, and Windows/macOS Extended Stable moved to 148.0.7778.254 on 2026-06-03. |
| Researcher / reporting source | Chrome stable bulletin says Reported by Google on 2026-05-14. |
| Scanning / exposure data | Shodan/Censys-style internet exposure counts are not meaningful here because Chrome is an endpoint browser, not an internet-facing daemon. Exposure should be measured by fleet version inventory and browser update telemetry, not public attack-surface scans. |
| Disclosure date | Your provided disclosure date is 2026-06-04; the public stable desktop fix was released on 2026-06-02, with Android on 2026-06-02 and Extended Stable on 2026-06-03. |
Sources.
- Chrome Releases - Stable Channel Update for Desktop (2026-06-02)
- Chrome Releases - Extended Stable Updates for Desktop (2026-06-03)
- Chrome Releases - Chrome for Android Update (2026-06-02)
- Chromium Security - Site Isolation
- Chromium Security - chrome://sandbox Diagnostics for Windows
- Chromium design doc - GPU accelerated compositing in Chrome
- CISA Known Exploited Vulnerabilities Catalog
- FIRST EPSS
Why this verdict
- Major downward adjustment: exploitation requires a *compromised renderer process*, which implies the attacker already owns a separate Chrome bug and is now chaining this one post-initial-exploit.
- Population is narrower than CVSS suggests: every target must be on a vulnerable Chrome build *and* on a platform/runtime path that exercises the vulnerable ANGLE/GPU behavior reliably.
- Threat intel is cold: no KEV listing, no public PoC found, and the provided EPSS is extremely low, which argues against broad opportunistic weaponization.
Why not higher?
If this were reachable directly from a crafted page without the renderer-compromise prerequisite, it would stay in HIGH or worse. But a bug that only becomes useful *after* a separate browser exploit is materially less urgent for defenders managing patch queues across 10,000 hosts. Also, out-of-bounds read is usually a weaker primitive than direct write/UAF primitives for stable one-shot compromise.
Why not lower?
This still sits in the browser exploit-chain space, and Chrome is everywhere. If an attacker already has renderer code execution, a vulnerable cross-process graphics component is exactly the kind of second-stage primitive used to cross security boundaries, so this is not mere hygiene backlog.
Crowdsourced verification payload.
Run this on the target endpoint or through your software inventory agent. Invoke with python3 check_chrome_cve_2026_10889.py on Windows/macOS/Linux; no admin rights are required if Chrome is installed in standard user- or system-level locations. The script checks common Chrome/Chromium paths, extracts the local version, and prints VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
# check_chrome_cve_2026_10889.py
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
from pathlib import Path
FIXED_MIN = (149, 0, 7827, 53)
EXT_STABLE_WIN_MAC = (148, 0, 7778, 254)
ANDROID_FIXED = (149, 0, 7827, 59) # documented for reference; this script is desktop-focused
def parse_ver(s):
m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', s or '')
if not m:
return None
return tuple(int(x) for x in m.groups())
def ver_str(v):
return '.'.join(str(x) for x in v) if v else 'UNKNOWN'
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 99, ''
def candidate_commands():
system = platform.system().lower()
cmds = []
if system == 'windows':
local = os.environ.get('LOCALAPPDATA', '')
pf = os.environ.get('PROGRAMFILES', '')
pf86 = os.environ.get('PROGRAMFILES(X86)', '')
candidates = [
Path(local) / 'Google/Chrome/Application/chrome.exe',
Path(pf) / 'Google/Chrome/Application/chrome.exe',
Path(pf86) / 'Google/Chrome/Application/chrome.exe',
Path(local) / 'Chromium/Application/chrome.exe',
Path(pf) / 'Chromium/Application/chrome.exe',
Path(pf86) / 'Chromium/Application/chrome.exe',
]
for c in candidates:
if c.exists():
cmds.append([str(c), '--version'])
elif system == 'darwin':
candidates = [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
str(Path.home() / 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
'/Applications/Chromium.app/Contents/MacOS/Chromium',
str(Path.home() / 'Applications/Chromium.app/Contents/MacOS/Chromium'),
]
for c in candidates:
if Path(c).exists():
cmds.append([c, '--version'])
else:
for name in ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']:
p = shutil.which(name)
if p:
cmds.append([p, '--version'])
return cmds
def classify(version_tuple):
major = version_tuple[0]
# Windows/macOS Extended Stable backport documented at 148.0.7778.254
if major == 148 and version_tuple >= EXT_STABLE_WIN_MAC:
return 'PATCHED'
if version_tuple >= FIXED_MIN:
return 'PATCHED'
return 'VULNERABLE'
def main():
cmds = candidate_commands()
if not cmds:
print('UNKNOWN - Chrome/Chromium executable not found in common locations')
sys.exit(2)
seen = []
for cmd in cmds:
rc, out = run_cmd(cmd)
v = parse_ver(out)
seen.append((cmd[0], v, out))
if v:
state = classify(v)
print(f'{state} - {cmd[0]} version {ver_str(v)}')
sys.exit(0 if state == 'PATCHED' else 1)
print('UNKNOWN - Found browser executable(s) but could not parse version')
for path, v, out in seen:
print(f'Checked: {path} | Raw: {out}')
sys.exit(2)
if __name__ == '__main__':
main()