This is a flaw in the bank vault’s inner cage, not the lobby door
CVE-2026-10938 affects Google Chrome prior to 149.0.7827.53 on Linux and prior to 149.0.7827.53/54 on Windows and macOS. The user-supplied title says *"Inappropriate implementation in Input"*, but Google’s June 2, 2026 stable-channel advisory lists it as *"Insufficient validation of untrusted input in Input"* and tags it High in Chromium’s internal severity language. The important part is the attack precondition: the attacker must already have compromised the renderer process before this bug matters.
In practice, that makes this a post-initial-compromise browser chain component, not a stand-alone drive-by. Vendor-style wording can make these look scarier than they usually are in enterprise triage because *site-isolation/sandbox-boundary* bugs sit behind another exploit stage. Still, this is not ignorable: if an attacker already has renderer code execution, a boundary-bypass in Chrome can turn a contained foothold into cross-origin data access or a stronger follow-on position. That keeps it above LOW, but the renderer-compromise prerequisite drags it down to = ASSESSED AT MEDIUM.
4 steps from start to impact.
Land renderer compromise first
- Victim browses attacker-controlled content
- A separate renderer compromise primitive exists and works against the victim build
- Chrome process mitigations do not stop the stage-one exploit
- This CVE does nothing by itself; another exploit must already succeed
- Modern Chrome hardening and rapid auto-update reduce the usable population for the first-stage bug
- Exploit chaining is materially harder than single-bug web compromise
Trigger the Input bug as stage two
- Renderer process already under attacker influence
- Victim is on a vulnerable Chrome build before
149.0.7827.53/54 - Attacker can deliver crafted HTML/content to the live session
- Official bug details are restricted, which slows commodity weaponization
- No public PoC was identified in the reviewed sources
- Per-build reliability is usually fragile for browser chain components
Bypass site isolation / browser boundary
- Vulnerable Input path reachable from the compromised renderer
- Useful target data or cross-origin context exists in the browser session
- Blast radius is bounded by what the browser session actually has open and accessible
- Some enterprise controls reduce value, such as separate profiles, ephemeral sessions, and forced sign-out patterns
- This is still browser-internal abuse, not direct domain-controller magic
Monetize via session theft or follow-on access
- High-value authenticated web sessions present in the browser
- Attacker has infrastructure to exfiltrate or act on stolen session material
- MFA does not help much once live browser session artifacts are stolen, but short session lifetimes and reauth policies do
- Not every compromised browser is carrying valuable authenticated sessions at the moment of exploitation
- Perimeter scanning doesn't help; this is a client-side browser flaw, not an exposed server port.
- WAF rules do not meaningfully mitigate a renderer-compromise chain inside the user’s browser session.
- MFA alone is not a control here; if an attacker steals live browser session artifacts after compromise, MFA has already been bypassed at the session layer.
The supporting signals.
| In-the-wild status | No confirmed active exploitation in reviewed sources. Not listed in CISA KEV, and Google’s release post does not note in-the-wild abuse. |
|---|---|
| Public exploit / PoC | No public PoC identified. The Chromium issue reference exists, but bug details are restricted, which is normal while fixes propagate. |
| EPSS | 0.00021 (~0.021%) from the user-supplied intel. That is very low modeled near-term exploitation probability; percentile was not confirmed in the reviewed sources. |
| KEV status | Not KEV-listed as of the reviewed CISA catalog page. |
| Vendor severity language | High in Chromium’s advisory taxonomy, but no vendor/authority CVSS score was published in the sources reviewed. |
| Affected versions | Chrome Desktop before 149.0.7827.53 on Linux and before 149.0.7827.53/54 on Windows/macOS. |
| Fixed versions | Patched in 149.0.7827.53 (Linux) and 149.0.7827.53/54 (Windows/macOS). Android 149.0.7827.59 inherits the corresponding desktop security fixes. For distro-packaged Chromium, verify backports in distro changelogs instead of comparing only upstream version strings. |
| Reachability reality check | Requires attacker position = compromised renderer. That implies a prior successful browser exploit stage. This is major downward pressure on operational severity. |
| Scanning / exposure data | Shodan/Censys/FOFA are mostly irrelevant here. Chrome is a client application, not an internet-facing service, so classic exposure counting does not meaningfully rank risk for this CVE. |
| Disclosure / reporting timeline | Google’s stable-channel advisory was published June 2, 2026; Canada’s Cyber Centre echoed it June 3, 2026. Chrome’s release notes say CVE-2026-10938 was reported by Google on April 14, 2026. |
Sources.
Why this verdict
- Big downgrade for attacker position — exploitation requires a compromised renderer process, which implies the attacker has already landed a separate browser exploit stage. That sharply narrows real-world reach versus a normal unauthenticated web RCE.
- Still a real security boundary issue — once chained, this can undermine site isolation / containment and expose higher-value browser session data. On a workforce fleet full of SSO sessions, that is materially useful to an operator.
- Threat intel is cool, not hot — no KEV, no public PoC found, and EPSS is only 0.00021. That is weak evidence for broad near-term exploitation pressure.
Why not higher?
It is not higher because this is not a one-bug compromise path. Requiring prior renderer compromise means the attacker is already inside Chrome’s sandbox lane, so the reachable population is the subset of users who are also vulnerable to a separate stage-one exploit and are worth chaining against.
Why not lower?
It is not lower because site-isolation and browser-boundary bypasses are valuable once a browser foothold exists. In enterprises, a chained browser exploit can expose live SaaS sessions, tokens, and cross-origin data that materially increase attacker payoff even without host-level code execution.
Crowdsourced verification payload.
Run this on the target endpoint or through your endpoint management agent, not from an auditor workstation. Invoke it with python3 chrome_cve_2026_10938_check.py on macOS/Linux or py chrome_cve_2026_10938_check.py on Windows; standard user rights are usually enough because it only reads local install metadata and runs --version.
#!/usr/bin/env python3
# CVE-2026-10938 Chrome version check
# Outputs: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
from pathlib import Path
PATCH_MIN = (149, 0, 7827, 53)
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')
def parse_version(text):
m = VERSION_RE.search(text or '')
if not m:
return None
return tuple(int(x) for x in m.groups())
def run_version(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 parse_version(out), out.strip()
except Exception:
return None, ''
def candidate_paths():
system = platform.system().lower()
paths = []
if system == 'windows':
envs = [
os.environ.get('PROGRAMFILES'),
os.environ.get('PROGRAMFILES(X86)'),
os.environ.get('LOCALAPPDATA'),
]
suffixes = [
r'Google\Chrome\Application\chrome.exe',
r'Chromium\Application\chrome.exe',
]
for base in envs:
if not base:
continue
for suffix in suffixes:
paths.append(str(Path(base) / suffix))
elif system == 'darwin':
paths.extend([
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
str(Path.home() / 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
str(Path.home() / 'Applications/Chromium.app/Contents/MacOS/Chromium'),
])
else:
for name in ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']:
found = shutil.which(name)
if found:
paths.append(found)
paths.extend([
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'/snap/bin/chromium',
'/opt/google/chrome/chrome',
])
# de-duplicate while preserving order
seen = set()
uniq = []
for p in paths:
if p and p not in seen:
uniq.append(p)
seen.add(p)
return uniq
def compare_version(v):
return v >= PATCH_MIN
def main():
tested = []
found_any = False
for path in candidate_paths():
if os.path.exists(path) or shutil.which(path):
found_any = True
version, raw = run_version([path, '--version'])
tested.append((path, version, raw))
if version is not None:
if compare_version(version):
print(f'PATCHED - {path} - version {".".join(map(str, version))}')
sys.exit(0)
else:
print(f'VULNERABLE - {path} - version {".".join(map(str, version))}')
sys.exit(1)
if not found_any:
print('UNKNOWN - Chrome/Chromium executable not found in common locations')
sys.exit(2)
# Found something but could not parse any version
print('UNKNOWN - Found browser executable(s) but could not parse version')
for path, version, raw in tested:
msg = raw.replace('\n', ' ').strip()
if len(msg) > 120:
msg = msg[:117] + '...'
print(f'INFO - {path} - raw output: {msg}')
sys.exit(2)
if __name__ == '__main__':
main()