This is a second lock on the vault door, not the street-facing window
CVE-2026-10921 is an integer overflow in Dawn, Chromium's WebGPU implementation, affecting Google Chrome before 149.0.7827.53. The key qualifier in the vendor description matters more than the bug class: the attacker must already have compromised the renderer process and then use this flaw to push malformed WebGPU/Dawn inputs toward a more privileged process boundary.
Google's HIGH 8.3 label is technically defensible because a compromised renderer to GPU/browser-process memory corruption path is exactly the kind of bug that can become a sandbox-escape building block. But in real enterprise risk terms, this is not initial access and not a clean drive-by; it is a post-compromise chain component with very low EPSS and no KEV listing, so the vendor score overstates the urgency for defenders triaging across 10,000 endpoints.
4 steps from start to impact.
Land code execution in the renderer
- Victim runs a vulnerable Chrome build before 149.0.7827.53
- Attacker already has a renderer compromise from another bug or execution path
- A reachable WebGPU/Dawn code path exists in the victim's build/platform
- This CVE does not provide renderer compromise on its own
- Modern browser exploit chains need at least one additional bug before this CVE becomes useful
- Some enterprise fleets reduce reachable attack surface with hardware/feature policy controls
Abuse Dawn/WebGPU input handling
- WebGPU/Dawn path is enabled and reachable on the target platform
- Attacker can execute JavaScript and/or native logic inside the compromised renderer
- The vulnerable code path is exposed in the victim's exact Chrome build
- WebGPU paths are complex and exploit reliability can be highly platform-specific
- Graphics stack behavior varies by OS, GPU, driver, and software rendering path
- Integer-overflow bugs often need careful heap shaping to move from crash to controlled corruption
Cross the sandbox boundary
- Corruption lands in a process with privileges beyond the renderer sandbox
- The exploit can shape memory precisely enough for useful impact
- Platform mitigations do not terminate the process before weaponization
- A crash is far easier than reliable code execution
- Sandboxing, process isolation, CFG/CFI, and allocator hardening all raise exploit cost
- On many fleets, turning this into durable host compromise still needs another step
Chain to host-level objectives
- Attacker successfully weaponizes the bug into more than a denial-of-service crash
- The endpoint has valuable sessions, secrets, or reachable follow-on paths
- Endpoint controls do not contain the post-escape activity
- This CVE alone does not guarantee OS-level execution
- Credential protections, browser isolation, and EDR can still limit value after exploitation
- Enterprise blast radius is user-context centric unless the attacker adds further escalation
The supporting signals.
| In-the-wild status | No public exploitation evidence located in primary sources reviewed, and not listed in CISA KEV at time of assessment. This materially lowers urgency versus Chrome flaws that arrive with zero-day reporting. |
|---|---|
| Proof-of-concept availability | No public PoC or exploit repo found for CVE-2026-10921 in primary-source review. Expect private exploitability to be plausible for advanced actors because Dawn/WebGPU has known research attention, but there is no public weaponization signal here. |
| EPSS | 0.00068 (~0.068%) from the supplied intel, which is very low. The exact percentile was not supplied; based on FIRST's 2026-06-04 EPSS distribution, that score sits roughly in the low-20th percentile *(inference, not a direct API lookup for this CVE)*. |
| KEV status | Not KEV-listed as of this review. If CISA later adds it, the severity and timeline should be revisited immediately because Chrome chain bugs move fast once public exploit chains stabilize. |
| CVSS vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H from the supplied vendor intel. The important real-world translation is: user interaction plus high complexity plus chained exploitation assumptions. |
| Affected versions | Affected: Google Chrome before 149.0.7827.53 per supplied advisory metadata. Chrome release notes show 149.0.7827.53/.54 as the early stable desktop build and 149.0.7827.53 on Beta for desktop. |
| Fixed versions | Fixed in 149.0.7827.53/.54 for Windows and Mac early stable and 149.0.7827.53 on Beta for Windows/Mac/Linux based on Chrome release pages. For fleet ops, treat 149.0.7827.53 or later as the minimum safe floor unless your channel-specific packaging says otherwise. |
| Scanning / exposure reality | Shodan/Censys/FOFA are not meaningful here because this is a client-side browser component, not an internet-listenable service. Exposure is determined by endpoint version inventory and policy state, not external attack-surface scans. |
| Disclosure date | 2026-06-04 from the supplied intel. Chrome 149.0.7827.53/.54 was already present in release channels on 2026-05-29, which suggests patch availability closely bracketed disclosure. |
| Researcher / reporting | No public credit found in the reviewed primary sources. Chrome often withholds details until users are broadly updated, so the absence of attribution here is not unusual. |
noisgate verdict.
The single biggest severity reducer is the prerequisite: the attacker must already control the renderer process. That means this CVE is best understood as a sandbox-escape building block, not an enterprise-scale initial-access event, and the lack of KEV/public exploitation evidence keeps it out of the top patch queue.
Why this verdict
- Requires prior compromise: this is not unauthenticated remote code execution from the open internet; it assumes the attacker already won code execution inside the renderer.
- Exposure population narrows hard: every added prerequisite compounds downward pressure — user interaction, a first-stage browser bug, then a reachable Dawn/WebGPU path, then reliable privilege-boundary crossing.
- Threat intel is quiet: no KEV entry, no public exploit kit/PoC located, and a very low EPSS score all argue against treating this like a break-glass Chrome zero-day.
Why not higher?
If this were exploitable from a malicious page without the renderer-compromise prerequisite, it would stay in HIGH or climb higher because Chrome is ubiquitous and browser compromise is high-value. But once you force the attacker to bring their own renderer RCE first, you have moved from initial-access risk to chain-completion risk.
Why not lower?
It still sits above LOW because the vulnerable component lives in a massively deployed browser and the likely outcome is not just a tab crash; it is a potential sandbox-boundary bypass primitive. Chromium's own security guidance treats compromised-renderer-to-higher-privilege memory corruption as strategically important, so ignoring it would be complacent.
What to do — in priority order.
- Enforce browser auto-update health — Validate that Chrome update services, package repos, and MDM policies are actually advancing endpoints to 149.0.7827.53+. For a MEDIUM noisgate verdict there is no mitigation SLA — go straight to the 365-day remediation window — but auto-update drift is the main operational reason browser bugs linger.
- Disable or restrict WebGPU where unused — If your user base does not need WebGPU, use enterprise browser policy or managed configuration to reduce reachability of Dawn attack paths. There is no mitigation SLA for MEDIUM, so treat this as a risk-reduction option for higher-risk user groups rather than a fleet-wide emergency control.
- Prioritize high-risk cohorts — Move developers, researchers, executives, help desk, and users who browse untrusted content into the first browser update ring. The bug is most relevant where attackers are likely to chain browser exploits, even though the noisgate severity does not justify an emergency fleet-wide scramble.
- Watch for browser crash clusters — Hunt for unusual renderer/GPU-process crash spikes and browser instability after suspicious browsing events. This will not prove exploitation, but it is one of the few practical signals for failed or partially successful chain attempts.
- A WAF does not help; this is a client-side browser bug, not a server-side request path problem.
- Perimeter scanning does not help; Shodan/Censys-style visibility cannot tell you which endpoints have a vulnerable browser build.
- MFA is good hygiene but irrelevant to preventing the vulnerability trigger itself.
Crowdsourced verification payload.
Run this on the target endpoint or via your software inventory/remote execution platform. Invoke it with python3 chrome_cve_2026_10921_check.py on macOS/Linux or py chrome_cve_2026_10921_check.py on Windows; it needs standard user privileges only because it reads local application metadata and common install paths.
#!/usr/bin/env python3
# CVE-2026-10921 Chrome version check
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import os
import platform
import re
import subprocess
import sys
from pathlib import Path
MIN_VERSION = (149, 0, 7827, 53)
def parse_version(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 version_str(v):
return '.'.join(str(x) for x in v)
def get_windows_versions():
candidates = [
r'C:\Program Files\Google\Chrome\Application\chrome.exe',
r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe',
os.path.expandvars(r'%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe'),
]
found = []
try:
import winreg # type: ignore
reg_paths = [
(winreg.HKEY_CURRENT_USER, r'Software\Google\Chrome\BLBeacon', 'version'),
(winreg.HKEY_LOCAL_MACHINE, r'Software\Google\Chrome\BLBeacon', 'version'),
(winreg.HKEY_LOCAL_MACHINE, r'Software\WOW6432Node\Google\Chrome\BLBeacon', 'version'),
]
for hive, path, name in reg_paths:
try:
with winreg.OpenKey(hive, path) as k:
val, _ = winreg.QueryValueEx(k, name)
v = parse_version(str(val))
if v:
found.append(('registry:' + path, v))
except OSError:
pass
except Exception:
pass
for c in candidates:
if os.path.exists(c):
try:
out = subprocess.check_output([
'powershell', '-NoProfile', '-Command',
f"(Get-Item '{c}').VersionInfo.ProductVersion"
], stderr=subprocess.DEVNULL, text=True, timeout=10).strip()
v = parse_version(out)
if v:
found.append((c, v))
except Exception:
pass
return found
def get_macos_versions():
candidates = [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
str(Path.home() / 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
]
found = []
for c in candidates:
if os.path.exists(c):
try:
out = subprocess.check_output([c, '--version'], stderr=subprocess.DEVNULL, text=True, timeout=10).strip()
v = parse_version(out)
if v:
found.append((c, v))
except Exception:
pass
plist_candidates = [
'/Applications/Google Chrome.app/Contents/Info.plist',
str(Path.home() / 'Applications/Google Chrome.app/Contents/Info.plist'),
]
for p in plist_candidates:
if os.path.exists(p):
try:
out = subprocess.check_output(['/usr/libexec/PlistBuddy', '-c', 'Print :KSVersion', p], stderr=subprocess.DEVNULL, text=True, timeout=10).strip()
v = parse_version(out)
if v:
found.append((p, v))
except Exception:
pass
return found
def get_linux_versions():
commands = [
['google-chrome', '--version'],
['google-chrome-stable', '--version'],
['chromium-browser', '--version'],
['chromium', '--version'],
]
found = []
for cmd in commands:
try:
out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True, timeout=10).strip()
v = parse_version(out)
if v:
found.append((' '.join(cmd), v))
except Exception:
pass
for p in ['/opt/google/chrome/chrome', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable']:
if os.path.exists(p):
try:
out = subprocess.check_output([p, '--version'], stderr=subprocess.DEVNULL, text=True, timeout=10).strip()
v = parse_version(out)
if v:
found.append((p, v))
except Exception:
pass
return found
def dedupe(found):
seen = set()
result = []
for path, ver in found:
key = (path, ver)
if key not in seen:
seen.add(key)
result.append((path, ver))
return result
def main():
system = platform.system().lower()
if 'windows' in system:
found = get_windows_versions()
elif 'darwin' in system:
found = get_macos_versions()
else:
found = get_linux_versions()
found = dedupe(found)
if not found:
print('UNKNOWN: Google Chrome not found or version could not be determined')
sys.exit(2)
best = max((ver for _, ver in found))
best_paths = [path for path, ver in found if ver == best]
if best >= MIN_VERSION:
print(f'PATCHED: detected Chrome {version_str(best)} at {best_paths[0]} (minimum safe version {version_str(MIN_VERSION)})')
sys.exit(0)
else:
print(f'VULNERABLE: detected Chrome {version_str(best)} at {best_paths[0]} (requires >= {version_str(MIN_VERSION)})')
sys.exit(1)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
- Chrome Releases: Early Stable Update for Desktop (149.0.7827.53/.54)
- Chrome Releases: Chrome Beta for Desktop Update (149.0.7827.53)
- Chromium Security Severity Guidelines
- Chromium Threat Model and Defenses Against Compromised Renderers
- Chromium WebGPU Technical Report
- FIRST EPSS API Documentation
- CISA Known Exploited Vulnerabilities Catalog
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.