This is a loaded nail gun left on every employee desk, but it still needs the user to pick it up and the attacker to aim perfectly
CVE-2026-10886 is a use-after-free in Chrome FileSystem fixed in Chrome 149.0.7827.53 for Linux and 149.0.7827.53/54 for Windows and macOS. Google lists it as affecting Chrome prior to those builds, and the vendor description plus CVSS imply a remote attacker can drive memory corruption from malicious web content with user interaction required.
Google's 9.6 / CRITICAL label is understandable in a lab because browser memory corruption plus scope change can mean full compromise. In the field, though, this is not the same as an unauthenticated server-side RCE: the attacker still needs a user to hit malicious content, then needs a reliable exploit path through modern Chrome hardening, and there is no KEV listing, no public exploitation evidence, and no public weaponized PoC surfaced from the sources reviewed.
4 steps from start to impact.
Get a user onto attacker-controlled web content
- Target uses vulnerable Chrome build
- Target visits attacker-controlled or attacker-influenced content
- Browser auto-update has not already moved the endpoint forward
- Requires UI:R; this is not a no-click daemon flaw
- Email security, DNS filtering, SWG, and browser isolation can break delivery
- Chrome's auto-update shrinks dwell time on managed fleets
Trigger the FileSystem use-after-free
- Victim renders the malicious content in vulnerable Chrome
- Exploit path reaches the affected FileSystem code path
- Attacker has a working primitive for this exact build family
- Chrome memory hardening, allocator behavior, and version drift make reliable exploitation brittle
- Exploit often needs build-specific offsets/timing
- Crash-only outcomes are more common than clean control-flow hijack in poorly matured browser exploits
Convert memory corruption into sandbox escape / privileged execution
- Successful memory corruption with control, not just crash
- A viable path past renderer containment or into a privileged process
- Target defenses do not interrupt unusual browser child-process or token activity
- Modern Chrome sandboxing, CFI-style hardening, and process isolation raise the exploit-development bar
- Many enterprises run EDR that will catch obvious post-browser execution
- A single bug does not automatically equal reliable whole-host compromise at scale
Run payloads or steal enterprise data
- Successful post-sandbox execution
- User context has access to interesting SaaS, files, or internal apps
- Payload delivery is not blocked by application control
- Least-privilege user accounts limit OS-level blast radius
- EDR, MFA, and browser session protections can reduce monetizable outcomes
- Payload staging is noisy compared with the initial browser crash/trigger stage
The supporting signals.
| In-the-wild status | No public exploitation evidence found in the reviewed sources, and the user-provided intel says KEV listed: No. |
|---|---|
| KEV status | Not in CISA KEV as of this assessment; browser Chrome entries do exist in KEV historically, which matters because this one is not there. |
| EPSS | 0.00068 from the user-provided intel — extremely low relative likelihood of observed exploitation in the next 30 days. |
| Vendor severity vs reality | Vendor labels it CRITICAL / 9.6 with AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H. I downgrade to HIGH because UI:R plus exploit-chain reliability against modern Chrome materially narrows real-world abuse. |
| Affected versions | Google says Chrome prior to 149.0.7827.53 (Linux) and prior to 149.0.7827.53/54 (Windows/Mac). |
| Fixed versions | Patch level is 149.0.7827.53 on Linux and 149.0.7827.53/54 on Windows/macOS. Early stable reached a small percentage of users on 2026-05-29; broad stable post is 2026-06-02. |
| Disclosure / reporting | Google stable advisory published 2026-06-02; Google lists the bug as reported by Andrew Boni on 2026-04-21. |
| Proof-of-concept availability | No public PoC or GitHub exploit repo found in the reviewed sources. That does not make it safe, but it does cut copy-paste attacker volume. |
| Exposure / scanning reality | Client-side browser issue: Shodan/Censys/GreyNoise style internet scanning is largely not applicable because Chrome endpoints are not normally directly fingerprintable as a remotely reachable service. Exposure is measured by endpoint version inventory, not external IP census. |
| Population and blast radius | Population is broad because Chrome is common across enterprises, but blast radius starts at one user session and only becomes enterprise-significant if the attacker clears the sandbox and lands useful identity material or code execution. |
noisgate verdict.
The single biggest reason this is HIGH instead of CRITICAL is that the attacker still needs a user to render malicious content and then needs a reliable browser exploit chain against modern Chrome defenses. Mass deployment of Chrome is an amplifier, but the absence of KEV/public exploitation and the exploit maturity required to convert a FileSystem UAF into a dependable sandbox escape keep this out of the top bucket.
Why this verdict
- Downward adjustment: requires user interaction — this is a browser-content bug, not a no-click service exploit; the attacker needs the victim to hit malicious content.
- Downward adjustment: exploit reliability is hard — a Chrome UAF is dangerous, but turning it into stable, cross-build sandbox escape against modern browser hardening is specialist work, not commodity work.
- Upward adjustment: Chrome is everywhere — if a working exploit exists, reachable population is huge because browsers are universal and sit next to identity tokens, SaaS sessions, and trusted user workflows.
- Downward adjustment: no current threat signal — no KEV listing, no public in-the-wild confirmation, and no public PoC found.
- Upward adjustment: scope-changing impact is plausible — the vendor vector claims
S:Cand fullC/I/Aimpact, so this is not patch-later hygiene even after downgrading.
Why not higher?
I did not leave this at CRITICAL because the path assumes both victim interaction and successful exploit maturation through Chrome's sandboxing and memory-hardening layers. In practice that is a much smaller and noisier attacker set than the population that can abuse a remotely reachable unauthenticated server bug.
Why not lower?
I did not push this to MEDIUM because this is still a memory-corruption bug in the dominant enterprise browser, with vendor-assessed scope change and potentially severe post-compromise outcomes. If an attacker has a working exploit, the user-to-identity payoff is real even without broad internet scan visibility.
What to do — in priority order.
- Force Chrome auto-update compliance — Use enterprise policy or your endpoint platform to verify Chrome update channels are healthy and that endpoints can actually reach Google's update infrastructure. For a HIGH verdict, deploy and validate this control within 30 days, with special focus on VDI images, kiosks, lab systems, and unmanaged remote laptops that often drift behind.
- Block or isolate unpatched browsers — Use EDR, NAC, conditional access, VDI posture checks, or SWG policy to restrict access for endpoints still below 149.0.7827.53/54. For a HIGH verdict, have the temporary enforcement path in place within 30 days so stale clients cannot linger indefinitely.
- Harden web delivery paths — Raise phishing-resistant controls around malicious page delivery: secure web gateway filtering, DNS filtering, browser isolation for high-risk users, and ad/malvertising suppression. These are compensating controls, not substitutes; for a HIGH verdict, tighten them within 30 days for the most exposed user groups first.
- Tune EDR for browser child-process abuse — Alert on
chrome.exeor Chrome child processes spawning unusual binaries, script interpreters, or LOLBins, and review browser crash clusters after suspicious web activity. For a HIGH verdict, deploy or validate these detections within 30 days because post-exploitation is where defenders still have leverage. - Prioritize high-risk user cohorts — Front-load executives, finance, admins, help desk, developers, and users who routinely touch unknown external content. For a HIGH verdict, complete that prioritization within 30 days even if full fleet hygiene takes longer.
- A network perimeter scanner does not solve this; Chrome is a client application, so you need endpoint version inventory rather than external port scanning.
- A WAF is irrelevant here because the attack target is the user's browser, not your web server.
- MFA alone does not prevent exploit trigger or local browser compromise; it only limits some downstream identity abuse.
- Generic 'user awareness' training is not enough on its own; drive-by and malvertising delivery paths do not rely on obviously suspicious emails.
Crowdsourced verification payload.
Run this on the target endpoint or via your EDR/management agent with standard user rights; admin is only needed if your tooling restricts registry reads on Windows. Invoke it with python3 check_chrome_cve_2026_10886.py on macOS/Linux or py check_chrome_cve_2026_10886.py on Windows. It checks common Chrome install locations and outputs VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
# check_chrome_cve_2026_10886.py
# Detects whether installed Google Chrome is below the fixed versions for CVE-2026-10886.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import subprocess
import sys
from pathlib import Path
FIX_LINUX = (149, 0, 7827, 53)
FIX_WIN_MAC = (149, 0, 7827, 53) # Treat .53 and .54 as patched; anything below .53 is vulnerable.
def parse_version(s):
m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', s)
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) if v else 'unknown'
def cmp_version(a, b):
return (a > b) - (a < b)
def run_cmd(cmd):
try:
out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL, text=True).strip()
return out
except Exception:
return None
def find_windows_version():
# Try registry first
try:
import winreg
reg_paths = [
r'SOFTWARE\Google\Chrome\BLBeacon',
r'SOFTWARE\WOW6432Node\Google\Chrome\BLBeacon'
]
for hive in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE):
for reg_path in reg_paths:
try:
key = winreg.OpenKey(hive, reg_path)
val, _ = winreg.QueryValueEx(key, 'version')
v = parse_version(val)
if v:
return v, 'registry'
except Exception:
pass
except Exception:
pass
# Fallback to executable paths
candidates = [
os.path.expandvars(r'%ProgramFiles%\Google\Chrome\Application\chrome.exe'),
os.path.expandvars(r'%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'),
os.path.expandvars(r'%LocalAppData%\Google\Chrome\Application\chrome.exe'),
]
for exe in candidates:
if exe and Path(exe).exists():
out = run_cmd([exe, '--version'])
v = parse_version(out or '')
if v:
return v, exe
return None, None
def find_macos_version():
app = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
if Path(app).exists():
out = run_cmd([app, '--version'])
v = parse_version(out or '')
if v:
return v, app
plist = '/Applications/Google Chrome.app/Contents/Info.plist'
if Path(plist).exists():
out = run_cmd(['/usr/libexec/PlistBuddy', '-c', 'Print :CFBundleShortVersionString', plist])
v = parse_version(out or '')
if v:
return v, plist
return None, None
def find_linux_version():
candidates = ['google-chrome', 'google-chrome-stable', 'chrome', 'chromium', 'chromium-browser']
for cmd in candidates:
out = run_cmd([cmd, '--version'])
v = parse_version(out or '')
if v:
return v, cmd
desktop_paths = [
'/opt/google/chrome/chrome',
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable'
]
for exe in desktop_paths:
if Path(exe).exists():
out = run_cmd([exe, '--version'])
v = parse_version(out or '')
if v:
return v, exe
return None, None
def main():
sysname = platform.system().lower()
if 'windows' in sysname:
version, source = find_windows_version()
fixed = FIX_WIN_MAC
elif 'darwin' in sysname:
version, source = find_macos_version()
fixed = FIX_WIN_MAC
elif 'linux' in sysname:
version, source = find_linux_version()
fixed = FIX_LINUX
else:
print('UNKNOWN: unsupported platform {}'.format(platform.system()))
sys.exit(2)
if not version:
print('UNKNOWN: Google Chrome version not found')
sys.exit(2)
if cmp_version(version, fixed) < 0:
print('VULNERABLE: installed Chrome {} from {} is below fixed {}'.format(version_str(version), source, version_str(fixed)))
sys.exit(1)
else:
print('PATCHED: installed Chrome {} from {} meets or exceeds fixed {}'.format(version_str(version), source, version_str(fixed)))
sys.exit(0)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
- Google Chrome Releases - Stable Channel Update for Desktop (2026-06-02)
- Google Chrome Releases - Early Stable Update for Desktop (2026-05-29)
- Chromium Security Page
- CISA Known Exploited Vulnerabilities Catalog
- Google Chrome security advisory AV26-544 (Canadian Centre for Cyber Security)
- CVE Record
- NVD entry
- FIRST EPSS API documentation
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.