This is a cracked peephole in the browser wall, not a door kicked off the hinges
CVE-2026-10993 is a heap buffer overflow in Chrome's Skia graphics stack. Google shipped the fix in the Stable Channel update published on 2026-06-02 for Chrome 149.0.7827.53 on Linux and 149.0.7827.53/.54 on Windows and macOS; anything earlier is in scope. The bug class and nearby Skia fix history point to malformed graphics/color-profile handling during renderer-side content processing, so the likely trigger is attacker-supplied web content rather than local admin abuse.
Google rated it MEDIUM 6.5, and that is roughly fair. The important reality check is that this is not remote code execution and not a sandbox escape by itself; it is a confidentiality leak that still requires a user to render malicious content. Wide Chrome deployment keeps it out of LOW, but the user-interaction requirement, renderer containment, and lack of exploitation evidence keep it well below the browser zero-day tier.
4 steps from start to impact.
Land malicious rendered content
- Unauthenticated remote delivery path to the victim browser
- Victim uses a vulnerable Chrome desktop build
- Victim loads attacker-controlled HTML or embedded graphic content
- Requires UI:R; this is not wormable or spray-and-own at the network edge
- Safe Browsing, email/link rewriting, and enterprise web filtering remove a chunk of commodity delivery paths
- Chrome auto-update reduces the vulnerable window on managed fleets
Trigger Skia parsing in the renderer
504160794 hardens ICC-related validation by rejecting unsupported channel counts and grid dimensions, which strongly suggests malformed color-profile parsing as the trigger surface.- Renderable content must reach the affected Skia code path
- The malformed structure must survive normal content parsing and validation
- Exploit reliability depends on a specific parser path, not just any page visit
- Modern browser hardening and allocator behavior can make a raw memory bug nontrivial to weaponize consistently
Convert the overflow into an information leak
- The heap corruption must be shaped into a stable read/leak primitive
- Useful secrets must be present in the affected process memory at trigger time
- Info leak primitives are useful, but they are usually only one stage in a larger chain
- Renderer-process memory is a narrower blast radius than host-level compromise
Use leaked data for follow-on abuse
- Attacker has a second-stage objective that benefits from leaked renderer memory
- The leaked data is actionable before the browser process exits or rotates state
- Requires a follow-on exploit or high-value data in memory to matter operationally
- EDR, browser isolation, and session controls reduce the payoff of a standalone leak
The supporting signals.
| In-the-wild status | No public vendor statement of active exploitation found, and not listed in the CISA KEV catalog. |
|---|---|
| Proof-of-concept availability | No public exploit or GitHub PoC surfaced in open search. What is public is the Skia fix commit tied to bug 504160794, which gives researchers useful root-cause clues. |
| EPSS | 0.00032 from the upstream intel you supplied — effectively near floor level, which fits the lack of exploitation chatter. |
| KEV status | No. No KEV listing date because it is not present in CISA KEV. |
| CVSS vector, translated | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N means internet-deliverable with no auth, but it still needs the victim to render attacker content; impact is confidentiality only. |
| Affected versions | Desktop Chrome before 149.0.7827.53 on Linux and before 149.0.7827.53/.54 on Windows/macOS, per Google's Stable Channel update and the Canadian Centre advisory. |
| Fixed versions | Vendor-fixed in 149.0.7827.53 (Linux) and 149.0.7827.53/.54 (Windows/macOS). I found no authoritative distro backport advisory tied specifically to this CVE yet; for Linux, verify your packaged Chrome/Chromium channel separately. |
| Technical root cause | The public Skia commit says: reject unsupported A2B/B2A channel counts and grid dimensions, check profile conversion failure, and avoid unsafe writes before validation. That smells like malformed ICC/color-profile handling rather than a broad generic rendering bug. |
| Scanning / exposure data | Internet exposure platforms like Shodan/Censys/FOFA are not useful here because this is a client browser vulnerability, not a server banner. Your real exposure source is EDR/MDM/software inventory, not internet scan telemetry. |
| Disclosure and researcher | Google published the fixed Stable build on 2026-06-02; the Cyber Centre notice followed on 2026-06-03. Google credits M. Fauzan Wijaya (Gh05t666nero) for CVE-2026-10993 in the release advisory. |
noisgate verdict.
The single biggest limiter is what the bug actually buys the attacker: an information leak in browser process memory, not code execution or host compromise. Wide Chrome exposure prevents a lower bucket, but the combination of user interaction and confidentiality-only impact keeps this squarely in MEDIUM.
Why this verdict
- User interaction drags this down:
UI:Rmeans the attacker still needs the victim to browse/render malicious content, which is materially different from an edge-service bug. - The outcome is an info leak, not RCE: the published vector is
C:H/I:N/A:N, so the attacker gets memory disclosure rather than direct code execution, persistence, or destructive impact. - Renderer containment narrows blast radius: even when triggered, the likely impact is limited to browser-process memory and follow-on exploit enablement, not an automatic jump to OS compromise.
- Wide deployment keeps it from LOW: Chrome is everywhere, delivery is internet-scale, and version-based detection is easy but runtime detection is poor, so this still deserves operational attention.
Why not higher?
There is no evidence here of active exploitation, KEV inclusion, or a direct path to code execution. A browser memory-disclosure bug that still needs user interaction is dangerous mainly as a chain enabler, not as a standalone mass-compromise event.
Why not lower?
Chrome is one of the most exposed user applications in the enterprise, and drive-by delivery over normal browsing paths is realistic. Even a confidentiality-only bug matters when it can leak process memory from a high-frequency target and potentially support later-stage exploitation.
What to do — in priority order.
- Enforce browser auto-update — Make sure managed endpoints are pinned to your supported Chrome update channel and actually receive it. For a MEDIUM noisgate verdict there is no mitigation SLA — go straight to the 365-day remediation window, but for browsers you should still collapse version drift quickly through normal desktop engineering.
- Block unmanaged or stale Chrome builds — Use MDM, EDR, NAC, or conditional access to flag endpoints still below
149.0.7827.53. This reduces the long tail of exceptions that auto-update does not fix cleanly, and it should be rolled into your normal remediation workflow within the 365-day remediation window. - Harden risky browsing paths — Keep Safe Browsing, DNS/web filtering, attachment detonation, and click-time URL rewriting enabled because the delivery vector is still attacker-supplied web content. These controls do not fix the bug, but they reduce the chance a user ever renders the malicious payload while you work through remediation.
- Prefer browser isolation for high-risk groups — For admins, finance, executives, and other phish-heavy populations, remote/browser isolation reduces direct renderer exposure to attacker content. Use it where you already have the platform rather than treating this CVE as a reason to build a new stack.
- A WAF does not help; there is no server-side component to shield.
- Perimeter vulnerability scanners will not meaningfully detect exploitable exposure because the vulnerable component is a desktop browser, not an internet-facing service.
- Generic AV signatures are weak value here; the meaningful fix is getting the browser version forward, not hoping a payload hash match catches a rendering bug.
Crowdsourced verification payload.
Run this on the target endpoint or through your fleet management/EDR live response tool. Invoke it with python3 check_chrome_cve_2026_10993.py on macOS/Linux or py check_chrome_cve_2026_10993.py on Windows; standard user rights are usually enough because it only reads installed version metadata.
#!/usr/bin/env python3
# check_chrome_cve_2026_10993.py
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import subprocess
import sys
TARGET = (149, 0, 7827, 53) # Treat 149.0.7827.53+ as fixed across platforms for this check.
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')
def parse_version(text):
if not text:
return None
m = VERSION_RE.search(text)
if not m:
return None
return tuple(int(x) for x in m.groups())
def cmp_ver(a, b):
return (a > b) - (a < b)
def run_cmd(cmd):
try:
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=10)
out = (p.stdout or '') + '\n' + (p.stderr or '')
return out.strip()
except Exception:
return ''
def detect_windows():
try:
import winreg
except Exception:
winreg = None
# First try BLBeacon registry keys used by Chrome.
if winreg:
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 key:
val, _ = winreg.QueryValueEx(key, name)
ver = parse_version(str(val))
if ver:
return ver, f'registry:{path}'
except Exception:
pass
# Fall back to executable version output.
candidates = [
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 exe in candidates:
if exe and os.path.exists(exe):
out = run_cmd([exe, '--version'])
ver = parse_version(out)
if ver:
return ver, exe
return None, ''
def detect_macos():
candidates = [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
]
for exe in candidates:
if os.path.exists(exe):
out = run_cmd([exe, '--version'])
ver = parse_version(out)
if ver:
return ver, exe
plist_candidates = [
'/Applications/Google Chrome.app/Contents/Info.plist',
os.path.expanduser('~/Applications/Google Chrome.app/Contents/Info.plist'),
]
for plist in plist_candidates:
if os.path.exists(plist):
out = run_cmd(['/usr/bin/defaults', 'read', plist, 'CFBundleShortVersionString'])
ver = parse_version(out)
if ver:
return ver, plist
return None, ''
def detect_linux():
candidates = [
['google-chrome', '--version'],
['google-chrome-stable', '--version'],
['/opt/google/chrome/chrome', '--version'],
]
for cmd in candidates:
out = run_cmd(cmd)
ver = parse_version(out)
if ver:
return ver, ' '.join(cmd)
return None, ''
def main():
system = platform.system().lower()
if 'windows' in system:
ver, src = detect_windows()
elif 'darwin' in system:
ver, src = detect_macos()
elif 'linux' in system:
ver, src = detect_linux()
else:
print('UNKNOWN - unsupported platform')
sys.exit(2)
if not ver:
print('UNKNOWN - Google Chrome version not found')
sys.exit(2)
if cmp_ver(ver, TARGET) >= 0:
print(f'PATCHED - detected Chrome version {".".join(map(str, ver))} via {src}')
sys.exit(0)
else:
print(f'VULNERABLE - detected Chrome version {".".join(map(str, ver))} via {src}')
sys.exit(1)
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.