This is a thief rifling through a room they already broke into, not a front-door lockpick
CVE-2026-11087 is an uninitialized memory use in ANGLE in Google Chrome fixed in 149.0.7827.53 and later. Public Chrome release notes list it as Medium and describe it simply as an ANGLE issue, while the CVE text adds the key real-world qualifier: the attacker must have already compromised the renderer process and then use a crafted HTML page to read potentially sensitive process memory.
Google's MEDIUM 6.5 label is fair in a vacuum, but for enterprise patch triage this lands lower. The decisive friction is the prerequisite: renderer compromise first. That means this is not a clean drive-by, not an edge-exposed service, and not a standalone enterprise entry point; it's a post-exploitation chain helper with confidentiality impact only.
3 steps from start to impact.
Win code execution inside the renderer first
- Attacker can get a target to load attacker-controlled web content
- A separate renderer-compromise bug or implant is already available
- Target is running Chrome prior to 149.0.7827.53
- This is post-initial-browser-compromise by definition
- Modern Chrome hardening, site isolation, and renderer sandboxing raise the bar before this CVE is even reachable
- No known public exploit chain specifically weaponizing this CVE
Steer execution into ANGLE with crafted graphics content
- Renderer code execution is already present
- ANGLE-backed rendering path is reachable on the endpoint
- The crafted page can exercise the vulnerable code path
- Hardware acceleration settings and platform differences can change reachability
- Uninitialized reads are often noisier and less deterministic than write primitives
- Enterprise browser policies may disable or constrain graphics features in some fleets
Harvest leaked memory and exfiltrate it
- Useful secrets are present in readable memory
- Attacker has a channel to exfiltrate recovered data
- Leaked bytes may be partial, stale, or operationally useless
- Site isolation and process separation limit what valuable data co-resides
- EDR/network controls may catch the exfiltration phase even if the read itself is silent
The supporting signals.
| In-the-wild status | No known active exploitation found in the sources reviewed, and the user-supplied intel says KEV listed: No. |
|---|---|
| KEV status | Not listed in CISA's KEV catalog as of 2026-06-05. |
| Proof-of-concept availability | No public PoC located for this specific CVE. Chromium notes that bug details may stay restricted until most users are patched. |
| EPSS | 0.00035 (user-supplied), which is effectively near-floor exploit probability for the next 30 days. |
| CVSS and meaning | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N scores the *technical* impact of a web-triggered info leak, but it does not capture the crucial renderer-compromise prerequisite in the CVE text. |
| Affected versions | Chrome prior to 149.0.7827.53. Chrome stable release notes show 149.0.7827.53 for Linux and 149.0.7827.53/54 for Windows/Mac on 2026-06-02. |
| Fixed versions | Upgrade to 149.0.7827.53 or later; in practice that means 149.0.7827.53+ on Linux and 149.0.7827.53/54+ on Windows/macOS depending on channel rollout. |
| Exposure and scanning reality | This is client software, not an internet-facing service. Shodan/Censys/GreyNoise-style exposure counts are largely not applicable; your real exposure surface is the count of endpoints running old Chrome builds. |
| Disclosure timeline | Patch shipped publicly on 2026-06-02 in Chrome 149 stable release notes; the user-supplied disclosure date is 2026-06-04, which likely reflects CVE publication timing rather than first fix availability. |
| Reporter | Chrome release notes list this bug as reported by Google on 2026-04-07. |
noisgate verdict.
The single biggest reason this lands LOW is that exploitation requires the attacker to have already compromised Chrome's renderer process. That prerequisite makes this a narrow post-compromise data-leak primitive, not a realistic standalone enterprise intrusion path.
Why this verdict
- Major downward adjustment: requires renderer compromise first — attacker position is effectively *already inside the browser sandbox*, which implies a prior successful exploit stage or implant.
- Population narrowing — every prerequisite compounds: web delivery + renderer compromise + ANGLE reachability + useful memory disclosure. That's a far smaller exposed population than Chrome's install base suggests.
- Blast radius is limited — impact is confidentiality from process memory, not direct code execution, persistence, or sandbox escape on its own.
- Threat intel is cold — no KEV listing, no public PoC found, and EPSS is effectively near zero.
- Defenders usually get this one 'for free' — Chrome auto-update and routine browser hygiene remediate it without emergency patch motion.
Why not higher?
If this were reachable by an unauthenticated remote attacker without prior renderer compromise, or if there were active chains using it for sandbox escape, this would jump fast. But the CVE text itself narrows it to a secondary-stage primitive, and that is the real severity governor.
Why not lower?
It still matters because Chrome is ubiquitous and browser exploit chains are real. An information leak inside a compromised renderer can expose secrets or help stabilize a bigger chain, so this is not 'IGNORE'—it's just not worth front-of-queue emergency patching.
What to do — in priority order.
- Keep Chrome auto-update healthy — For a LOW browser client issue, the best compensating control is simply making sure enterprise Chrome update rings are functioning and stalled clients are rare. There is no mitigation SLA for LOW findings, so treat this as backlog hygiene and verify compliance during your normal browser maintenance cycle.
- Reduce risky web rendering surface — Where business-tolerable, restrict high-risk browser features with enterprise policy, especially on privileged admin workstations and VDI pools. This does not replace patching, but it reduces exploit-chain room while you roll routine updates; for LOW, do this opportunistically rather than as an emergency change.
- Watch for browser exploit-chain signals — Hunt for clusters of Chrome renderer/GPU crashes, odd child-process behavior, and suspicious browser-originated outbound traffic. This matters because the real danger here is not the leak alone but its role in a larger browser compromise chain; again, no LOW mitigation SLA, so fold this into standard detection engineering.
- Prioritize privileged user tiers — If you have to clean up in rings, start with admins, developers, and high-value research users who browse widely and hold useful tokens in memory. There is no formal LOW remediation deadline, but these cohorts are where a post-compromise browser leak has the highest value.
- A WAF does not help; this is a client-side browser bug, not a server-side HTTP parsing problem.
- Perimeter network scanning does not measure exposure; Shodan-style visibility tells you almost nothing about unpatched Chrome on endpoints.
- Relying on CVSS alone overstates urgency here because CVSS does not encode the already-compromised-renderer prerequisite called out in the CVE description.
Crowdsourced verification payload.
Run this on the target endpoint or through your software-inventory automation. Invoke it as python3 chrome_cve_2026_11087_check.py to inspect common local Chrome installs, or python3 chrome_cve_2026_11087_check.py --version 149.0.7827.52 to check a version string from another tool; no admin privileges are required for the local checks.
#!/usr/bin/env python3
# CVE-2026-11087 Chrome version verifier
# Outputs one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import re
import sys
import subprocess
import platform
from pathlib import Path
FIXED = (149, 0, 7827, 53)
def parse_version(text):
if not text:
return None
m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', text)
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 compare(v1, v2):
return (v1 > v2) - (v1 < v2)
def run_cmd(cmd):
try:
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=5)
out = (p.stdout or '') + '\n' + (p.stderr or '')
return out.strip()
except Exception:
return ''
def find_from_commands():
candidates = [
['google-chrome', '--version'],
['google-chrome-stable', '--version'],
['chromium', '--version'],
['chromium-browser', '--version'],
['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '--version'],
]
for cmd in candidates:
out = run_cmd(cmd)
v = parse_version(out)
if v:
return ('command', ' '.join(cmd), v)
return None
def find_windows_file_version():
if os.name != 'nt':
return None
paths = [
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'),
]
for p in paths:
if p and os.path.exists(p):
ps = [
'powershell', '-NoProfile', '-Command',
f"(Get-Item '{p}').VersionInfo.ProductVersion"
]
out = run_cmd(ps)
v = parse_version(out)
if v:
return ('file', p, v)
return None
def find_macos_plist():
plist = Path('/Applications/Google Chrome.app/Contents/Info.plist')
if plist.exists():
out = run_cmd(['/usr/bin/defaults', 'read', str(plist), 'KSVersion'])
v = parse_version(out)
if v:
return ('plist', str(plist), v)
return None
def find_linux_paths():
paths = [
'/opt/google/chrome/chrome',
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/snap/bin/chromium',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
]
for p in paths:
if os.path.exists(p):
out = run_cmd([p, '--version'])
v = parse_version(out)
if v:
return ('file', p, v)
return None
def evaluate(v):
if compare(v, FIXED) >= 0:
print(f'PATCHED: Chrome version {version_str(v)} >= fixed {version_str(FIXED)}')
sys.exit(0)
else:
print(f'VULNERABLE: Chrome version {version_str(v)} < fixed {version_str(FIXED)}')
sys.exit(1)
def main():
if len(sys.argv) == 3 and sys.argv[1] == '--version':
v = parse_version(sys.argv[2])
if not v:
print('UNKNOWN: could not parse supplied version string')
sys.exit(2)
evaluate(v)
found = find_from_commands()
if not found and os.name == 'nt':
found = find_windows_file_version()
if not found and sys.platform == 'darwin':
found = find_macos_plist()
if not found and sys.platform.startswith('linux'):
found = find_linux_paths()
if not found:
print('UNKNOWN: Google Chrome version could not be determined on this host')
sys.exit(2)
source_type, source_path, v = found
# Commented source line for troubleshooting in automation logs
# print(f'DEBUG: source={source_type} path={source_path} version={version_str(v)}')
evaluate(v)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.