This is the second lock on the door after the burglar is already inside the lobby
CVE-2026-10969 is an input-validation flaw in Chrome's Extensions component affecting Google Chrome versions prior to 149.0.7827.53 on Linux and prior to the 149.0.7827.53/.54 desktop stable build on Windows and macOS. The important caveat is in the description itself: the attacker must already have *compromised the renderer process* and then use a crafted HTML page to cross into more privileged browser territory.
Google marked it HIGH at 7.5, which is fair in a lab because privilege-boundary failures inside a browser exploit chain matter. In enterprise reality, though, this is not a clean unauthenticated remote compromise by itself; it is a *post-renderer-compromise* escalation step with no public exploitation evidence, no KEV listing, and a very low EPSS signal, so the vendor score overstates the Monday-morning urgency.
4 steps from start to impact.
Land the user on attacker-controlled web content
- Victim uses Google Chrome on Windows, macOS, or Linux
- Victim visits attacker-controlled or attacker-influenced web content
- Chrome version is older than the fixed
149.0.7827.53family
- Requires user interaction (
UI:R) - Enterprise web filtering, browser isolation, and DNS security can cut off delivery
- This step is common, but still not sufficient to exploit this CVE
Exploit a separate renderer bug first
- A separate working renderer exploit exists
- The attacker can make that exploit fire in the victim's browsing session
- The renderer compromise survives long enough to pivot
- Implies a prior compromise stage; the attacker is already mid-chain
- Modern Chrome hardening, site isolation, and exploit mitigations raise development cost
- EDR/browser exploit telemetry may catch crashes, heap grooming, or suspicious browser behavior
Abuse Extensions trust boundaries from the owned renderer
- Renderer is already compromised
- Chrome Extensions component is at a vulnerable version
- The attack path reaches the affected extensions-related interface
- Exploit path is component-specific and requires precise browser-internals knowledge
- Not every renderer foothold cleanly reaches the vulnerable extension pathway
- Extension policy restrictions and hardened enterprise configs can narrow reachable surfaces
Convert browser privilege gain into endpoint impact
- Successful extension-layer privilege escalation
- Valuable browser data, sessions, or follow-on targets exist on the host
- This CVE does not by itself promise full OS compromise
- Blast radius is typically one browsing session or one endpoint at a time
- Attackers still need post-exploitation tradecraft to turn browser privilege into enterprise-scale impact
The supporting signals.
| In-the-wild status | No public evidence found in reviewed authoritative sources. Google did not flag this as exploited in the stable-channel advisory, and CISA KEV does not list it. |
|---|---|
| Public PoC availability | No public exploit or PoC was surfaced in the reviewed primary sources. The GHSA page shows no known source code entry. |
| EPSS | 0.00066 (0.066%, 21st percentile on GHSA), which is weak signal for near-term broad exploitation. |
| KEV status | Not KEV-listed in CISA's Known Exploited Vulnerabilities Catalog. |
| CVSS vector meaning | CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H says remote delivery is possible, but the AC:H and UI:R already hint this is not a point-and-shoot bug. The more important real-world friction is *unstated in CVSS shorthand*: it requires a pre-compromised renderer. |
| Affected versions | Google Chrome prior to 149.0.7827.53; desktop stable announcement covers 149.0.7827.53 on Linux and 149.0.7827.53/.54 on Windows/macOS. |
| Fixed versions | Upgrade to Chrome 149.0.7827.53 or later; for Windows/macOS the stable desktop release was 149.0.7827.53/.54. Downstream Chromium backports are vendor-specific and were not spelled out in the Chrome advisory. |
| Scanning / exposure reality | This is not internet-enumerable in any useful way via Shodan/Censys/FOFA because it is a client browser flaw, not a network-listening service. Exposure is best measured by endpoint inventory and browser version telemetry, not external attack-surface scans. |
| Disclosure / reporter | Disclosed 2026-06-05 in GHSA/NVD records. Chrome release notes show it was reported by Google on 2026-05-10 under Chromium issue 511765713. |
noisgate verdict.
The decisive factor is the attacker-position requirement: exploitation starts only *after* a separate renderer compromise, which makes this a post-initial-access browser-chain step rather than a standalone remote takeover. That sharply narrows both the reachable population and the number of attackers who can operationalize it, despite the high theoretical impact once chained.
Why this verdict
- Start from Google's 7.5 baseline because Chrome is everywhere and privilege-boundary failures inside browsers can absolutely matter when chained
- Downgrade hard for attacker position: the attacker must already have compromised the renderer process, which implies a prior exploit stage and makes this a second-stage chain component, not initial access
- Downgrade again for operational signal: no KEV listing, no public exploitation note from Google, and a very low EPSS (
0.066%) all argue against fleet-emergency treatment
Why not higher?
If this were a standalone remote code execution or sandbox escape with no prerequisite beyond visiting a page, HIGH would be fair and CRITICAL would be on the table if exploitation showed up. But the renderer-compromise prerequisite is a huge real-world narrowing factor, and that matters more than abstract C/I/A impact.
Why not lower?
Chrome is ubiquitous, and browser exploit chains are still one of the most practical ways to land on endpoints. A privilege-escalation step that helps an attacker escape renderer restrictions can materially change the outcome of a targeted campaign, so this is not backlog junk.
What to do — in priority order.
- Enforce Chrome auto-update and relaunch compliance — Use enterprise policy and device management to keep Chrome on the stable patched build and to force or strongly prompt relaunch for long-running sessions. For a
MEDIUMverdict there is no mitigation SLA; use this as part of the normal remediation window rather than an emergency control. - Tighten extension install policy — Restrict extension installation to an allowlist and remove unnecessary extensions to reduce reachable extensions-related attack surface. Again, for
MEDIUMthere is no mitigation SLA; do it within the standard remediation program if your fleet cannot update promptly. - Apply browser isolation to high-risk users — Put admins, executives, researchers, and users who routinely browse untrusted content behind remote browser isolation or hardened browsing profiles. This helps at the delivery and renderer-compromise stages, which is where this chain is most likely to be broken.
- Hunt for browser exploit signals — Review EDR telemetry for Chrome crashes, suspicious child processes, and abnormal access to browser profile data following untrusted web activity. This will not prove CVE-2026-10969 specifically, but it is where defenders have the best chance of seeing the chain.
- Perimeter vuln scanning doesn't help much because this is a client-side browser flaw, not a remotely enumerable service.
- MFA doesn't stop exploitation inside the browser; it only limits reuse of stolen sessions or credentials afterward.
- A WAF is mostly irrelevant unless it blocks the delivery site entirely; it cannot protect a local browser from its own vulnerable code path.
Crowdsourced verification payload.
Run this on the target endpoint or through your EDR/remote-exec tooling, not from an auditor workstation. Invoke it with python3 check_chrome_cve_2026_10969.py on macOS/Linux or py check_chrome_cve_2026_10969.py on Windows; no admin rights are normally required, but access to standard install paths is needed.
#!/usr/bin/env python3
# Check Google Chrome version for CVE-2026-10969
# Outputs one of: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
from typing import List, Optional, Tuple
THRESHOLD = (149, 0, 7827, 53)
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')
def parse_version(text: str) -> Optional[Tuple[int, int, int, int]]:
m = VERSION_RE.search(text or '')
if not m:
return None
return tuple(int(x) for x in m.groups())
def version_to_str(v: Tuple[int, int, int, int]) -> str:
return '.'.join(str(x) for x in v)
def run_and_get_version(cmd: List[str]) -> Optional[Tuple[int, int, int, int]]:
try:
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
out = (proc.stdout or '') + ' ' + (proc.stderr or '')
return parse_version(out)
except Exception:
return None
def candidate_commands() -> List[List[str]]:
cmds = []
system = platform.system().lower()
if system == 'windows':
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):
cmds.append([p, '--version'])
elif system == 'darwin':
mac_path = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
if os.path.exists(mac_path):
cmds.append([mac_path, '--version'])
if shutil.which('google-chrome'):
cmds.append(['google-chrome', '--version'])
else:
for name in ['google-chrome', 'google-chrome-stable', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable']:
if name.startswith('/'):
if os.path.exists(name):
cmds.append([name, '--version'])
elif shutil.which(name):
cmds.append([name, '--version'])
return cmds
def main() -> int:
found_versions = []
for cmd in candidate_commands():
v = run_and_get_version(cmd)
if v:
found_versions.append((cmd[0], v))
if not found_versions:
print('UNKNOWN: Google Chrome not found or version unreadable')
return 2
vulnerable = []
patched = []
for path, ver in found_versions:
if ver < THRESHOLD:
vulnerable.append((path, ver))
else:
patched.append((path, ver))
if vulnerable:
details = '; '.join(f'{path}={version_to_str(ver)}' for path, ver in vulnerable)
print(f'VULNERABLE: {details} (fixed at {version_to_str(THRESHOLD)} or later)')
return 1
if patched:
details = '; '.join(f'{path}={version_to_str(ver)}' for path, ver in patched)
print(f'PATCHED: {details}')
return 0
print('UNKNOWN: unable to classify installed Chrome version')
return 2
if __name__ == '__main__':
sys.exit(main())
If you remember one thing.
MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, with actual patching completed no later than 2027-06-05 under the noisgate remediation SLA. In practice, because Chrome updates cleanly and broadly, you should close this much sooner than the outer SLA limit, but it does not deserve the same queue position as standalone Chrome RCE or actively exploited sandbox escapes.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.