This is a crack in the vault wall, but only after the attacker is already inside the bank
CVE-2026-11004 is an out-of-bounds read in Chrome's ANGLE graphics layer, fixed in Chrome 149.0.7827.53 for Linux and 149.0.7827.53/.54 for Windows and Mac. In plain terms, malformed graphics-facing input can make Chrome read memory it should not, which typically means information disclosure or a crash rather than clean, first-shot code execution.
Reality is lower drama than a generic 'browser RCE' label would imply. Google published this specific record as Medium in the June 2, 2026 stable release notes, and the practical friction is decisive: the attacker has to first land a separate renderer compromise, so this bug is mainly useful as a second-stage chain helper rather than an initial access primitive.
4 steps from start to impact.
Land a renderer foothold first
- Target browses attacker-controlled content
- Attacker has a distinct renderer compromise primitive
- Chrome version is older than the fixed build
- Requires a prior browser exploit, which already narrows the attacker population to capable operators
- Modern browser hardening, site isolation, and exploit mitigations make first-stage renderer compromise non-trivial
- Exploit chain reliability drops sharply when two bugs must line up
Drive execution into ANGLE
ANGLE using hostile page content. The likely weaponized mechanism is crafted HTML/WebGL content that exercises the vulnerable memory-read path. This is a local-in-browser transition, not a network service exploit.- GPU/ANGLE path is reachable on the target platform
- Renderer can trigger the vulnerable code path
- Browser is using affected ANGLE code
- ANGLE behavior varies by OS, GPU, driver, and backend
- Some enterprise images reduce risky graphics paths via policy, VDI, or hardware acceleration controls
- Cross-platform browser bugs often lose reliability across heterogeneous fleets
Read unintended memory
- The malformed input reliably triggers the read
- Returned memory is attacker-usable
- Mitigations do not turn the bug into a harmless crash
- Read bugs often yield noisy crashes instead of useful disclosure
- Leaked data may be low-value or inconsistent between runs
- Memory safety hardening can reduce reliability or observability
Use the leak to improve a larger chain
- Attacker already has exploit-development maturity
- A second-stage privilege or sandbox bypass primitive exists
- Leaked memory materially improves chain reliability
- Requires multi-bug chaining and high operator skill
- Enterprise EDR/browser protections may catch the chain before useful impact
- No public in-the-wild evidence found as of 2026-06-05
149.0.7827.53+ and to close devices that have stalled update agents. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but in practice browsers should be folded into the next routine desktop patch wave, not left to drift for months.--no-sandbox, --disable-gpu-sandbox, unmanaged portable Chromium builds, and developer-channel browsers. This reduces the value of second-stage browser bugs while your standard remediation cycle catches up.- A WAF or perimeter IDS does not meaningfully help; exploitation happens inside the local browser's rendering and graphics path, not against a server you can front with HTTP filtering.
- MFA is unrelated to the vulnerability mechanics and does nothing to stop renderer-to-ANGLE memory corruption.
- Internet exposure scans will not answer the real question because this is an endpoint version-management problem, not a remotely enumerable listening service.
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found as of 2026-06-05; not listed in CISA KEV. |
|---|---|
| PoC availability | No public PoC or GitHub exploit repo was found in current source checks. The Chromium issue exists at issues.chromium.org/issues/494823889 but is access-restricted. |
| EPSS | User-provided EPSS is 0.00035. That is extremely low threat signal and consistent with a chain-only browser bug rather than mass exploitation. |
| KEV status | No in CISA's Known Exploited Vulnerabilities Catalog as checked on 2026-06-05. |
| Vendor severity / scoring | Google's Chrome stable release notes list CVE-2026-11004 as Medium severity, but no vendor CVSS score/vector was published. |
| Affected versions | Chrome versions before 149.0.7827.53 are affected; the stable rollout notes show 149.0.7827.53 for Linux and 149.0.7827.53/.54 for Windows/Mac. |
| Fixed versions | Upgrade to 149.0.7827.53 on Linux and 149.0.7827.53/.54 on Windows/Mac. |
| Scanning / exposure reality | This is an endpoint browser issue, not an internet-facing service. Shodan/Censys/FOFA-style exposure counts are not operationally useful; asset inventory and endpoint telemetry matter more. |
| Disclosure / reporting | Disclosed on 2026-06-04. Chrome release notes say it was reported by 86ac1f1587b71893ed2ad792cd7dde32 on 2026-03-22. |
| Comparable cases | Similar ANGLE memory issues have ranged from Medium chain helpers to High/Critical when they supported direct escape or write primitives; compare CVE-2023-1534 and CVE-2026-10889. This record landed in Chrome's Medium bucket. |
Sources.
- Chrome Releases - Stable Channel Update for Desktop (Chrome 149)
- Chrome Releases - Early Stable Update for Desktop
- Chromium issue tracker entry for CVE-2026-11004
- CISA Known Exploited Vulnerabilities Catalog
- FIRST EPSS data and statistics
- NVD - CVE-2023-1534 analogous ANGLE out-of-bounds read
- Chrome Releases - Stable Channel Update for Desktop (2023-03-21, CVE-2023-1534)
Why this verdict
- Baseline starts at Medium: Google's June 2, 2026 Chrome stable advisory publishes
CVE-2026-11004as a Medium issue and provides no CVSS score, so there is no numeric baseline to inherit. - Renderer compromise is the big downgrade pressure: requiring a prior renderer foothold implies the attacker already burned or bought a separate browser exploit. That is post-initial-access inside the browser security model, not broad one-click compromise across your fleet.
- Reachable population is narrower than Chrome's install base suggests: virtually every enterprise has Chrome, but only a tiny slice of real attacks will have both a renderer exploit and a reliable ANGLE follow-on path on the right OS/GPU/driver mix.
- Impact is read-only memory corruption: out-of-bounds read bugs are usually better at leaking memory or stabilizing another exploit than delivering direct, reliable code execution by themselves.
- Threat telemetry is quiet: user-provided EPSS is very low (
0.00035), there is no KEV entry, and no public PoC or campaign evidence was found as of 2026-06-05.
Why not higher?
This is not a clean unauthenticated remote compromise by itself. The need for prior renderer compromise is compounding friction, and there is no current evidence of active exploitation or a public exploit chain that turns this bug into a dependable enterprise-scale intrusion path.
Why not lower?
It still lives in a massively deployed internet-connected client and touches graphics parsing logic, which attackers routinely mine for exploit chains. Once a renderer foothold exists, even a read primitive can materially improve chain reliability or leak data that weakens sandbox isolation.
Crowdsourced verification payload.
Run this on the target endpoint or through your EDR/script runner. Invoke it as python3 chrome_cve_check.py or point it at a specific binary with python3 chrome_cve_check.py --path "/usr/bin/google-chrome"; no administrator privileges are required unless your environment restricts access to Chrome install paths or the Windows registry.
#!/usr/bin/env python3
# Check for Chrome versions vulnerable to CVE-2026-11004
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import argparse
import os
import platform
import re
import shutil
import subprocess
import sys
TARGET = (149, 0, 7827, 53)
def parse_version(text):
m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', text or '')
if not m:
return None
return tuple(int(x) for x in m.groups())
def ver_to_str(v):
return '.'.join(str(x) for x in v)
def run_cmd(cmd):
try:
r = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
out = (r.stdout or '') + (r.stderr or '')
return out.strip()
except Exception:
return ''
def get_windows_version_from_registry():
reg_paths = [
r'HKLM\Software\Google\Chrome\BLBeacon',
r'HKCU\Software\Google\Chrome\BLBeacon',
r'HKLM\Software\WOW6432Node\Google\Chrome\BLBeacon',
]
for reg_path in reg_paths:
out = run_cmd(['reg', 'query', reg_path, '/v', 'version'])
v = parse_version(out)
if v:
return v, f'registry:{reg_path}'
return None, None
def get_version_from_binary(path):
out = run_cmd([path, '--version'])
v = parse_version(out)
if v:
return v, path
return None, None
def candidate_paths(user_path=None):
paths = []
if user_path:
paths.append(user_path)
for name in ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']:
p = shutil.which(name)
if p:
paths.append(p)
system = platform.system().lower()
if system == 'darwin':
paths.extend([
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
])
elif system == 'windows':
local = os.environ.get('LOCALAPPDATA', '')
program_files = os.environ.get('ProgramFiles', '')
program_files_x86 = os.environ.get('ProgramFiles(x86)', '')
paths.extend([
os.path.join(local, 'Google', 'Chrome', 'Application', 'chrome.exe'),
os.path.join(program_files, 'Google', 'Chrome', 'Application', 'chrome.exe'),
os.path.join(program_files_x86, 'Google', 'Chrome', 'Application', 'chrome.exe'),
])
else:
paths.extend([
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/opt/google/chrome/chrome',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
])
seen = set()
deduped = []
for p in paths:
if p and p not in seen:
seen.add(p)
deduped.append(p)
return deduped
def main():
parser = argparse.ArgumentParser(description='Detect vulnerable Chrome versions for CVE-2026-11004')
parser.add_argument('--path', help='Explicit path to Chrome binary')
args = parser.parse_args()
system = platform.system().lower()
for p in candidate_paths(args.path):
if os.path.exists(p):
v, source = get_version_from_binary(p)
if v:
if v < TARGET:
print(f'VULNERABLE - detected Chrome version {ver_to_str(v)} from {source}; fixed version is {ver_to_str(TARGET)} or newer')
sys.exit(1)
else:
print(f'PATCHED - detected Chrome version {ver_to_str(v)} from {source}; meets or exceeds fixed version {ver_to_str(TARGET)}')
sys.exit(0)
if system == 'windows':
v, source = get_windows_version_from_registry()
if v:
if v < TARGET:
print(f'VULNERABLE - detected Chrome version {ver_to_str(v)} from {source}; fixed version is {ver_to_str(TARGET)} or newer')
sys.exit(1)
else:
print(f'PATCHED - detected Chrome version {ver_to_str(v)} from {source}; meets or exceeds fixed version {ver_to_str(TARGET)}')
sys.exit(0)
print('UNKNOWN - could not determine an installed Chrome version; provide --path to the browser binary or verify installation method')
sys.exit(2)
if __name__ == '__main__':
main()