This is a booby-trapped conference room, not a master key to the building
CVE-2026-9119 is a heap-based buffer overflow in Chrome's WebRTC component that can be triggered by attacker-controlled web content. Google and NVD describe the outcome as arbitrary code execution inside Chrome's sandbox via a crafted HTML page. The affected range is Chrome before 148.0.7778.179, with Google's May 19, 2026 desktop release notes showing 148.0.7778.178/179 for Windows/Mac and 148.0.7778.178 for Linux; Debian also backported fixes for Chromium.
The vendor's 8.8/HIGH is fair if you score the bug in isolation as remote code execution in a ubiquitous browser, but it overstates enterprise endpoint risk. The decisive reality is that exploitation lands in a sandboxed renderer, not straight on the host, and the attack still needs user interaction with malicious content. That combination makes this important patching work, but not an all-hands emergency absent a public exploit chain or sandbox escape.
5 steps from start to impact.
Lure the target into attacker content
- Target uses Chrome/Chromium in the vulnerable version range
- Victim visits attacker-controlled or attacker-influenced web content
- Standard browsing controls do not block the destination
- This is
UI:R, so there is no zero-click server-side reach - Email gateways, browser isolation, Safe Browsing, and URL filtering cut a lot of commodity delivery paths
- Many enterprise users never meaningfully touch WebRTC-heavy content outside a browser session
Trigger the WebRTC parser/processing path
- WebRTC is enabled and available in the browsing session
- The victim browser actually executes the attacker's page logic
- If WebRTC is disabled or restricted for high-risk tiers, this path can break
- Enterprise browser hardening and script restrictions can reduce reachable surface
Exploit the heap overflow in the renderer
WebRTC, yielding attacker-controlled code execution in the renderer process. Google's release note and NVD both explicitly state the code execution is inside a sandbox, which matters more operationally than the raw 'RCE' label.- The page reliably reaches the vulnerable memory state
- Exploit mitigations do not stop the corruption from becoming code execution
- Modern browser exploit development is hard: ASLR, CFI, process isolation, and ongoing hardening raise the bar
- No public PoC or exploit chain was found in targeted web searches as of 2026-06-03
Operate within the sandboxed renderer
- Renderer compromise succeeded
- The attacker can accomplish their objective without escaping the sandbox
- The sandbox sharply limits post-exploitation blast radius
- Cross-site theft is harder because modern desktop Chrome uses Site Isolation by default
- Full endpoint compromise usually needs a second bug or misconfiguration
Chain to something bigger
- A second exploit or abuse path exists
- Security tooling does not stop the follow-on activity
- This CVE alone does not grant host-level execution
- The chain complexity is materially higher than the vendor base score implies
- Perimeter vulnerability scanning does not solve this, because there is no remotely exposed service banner to find on the endpoint.
- Server-side WAF rules are mostly irrelevant; the exploit executes in the client browser, not on your web server.
- Network IDS alone is weak coverage because browser traffic is typically encrypted and the trigger can look like ordinary web activity.
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found in reviewed sources as of 2026-06-03. |
|---|---|
| KEV status | CISA KEV: not listed as of 2026-06-03. |
| PoC availability | No public PoC or weaponized exploit repo was found in targeted web searches; the Chromium issue reference is permission-gated. |
| EPSS | 0.00022 (0.022%) from the user-supplied intel, which is *very low* predictive exploitation pressure. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — the important real-world terms are network-deliverable, no auth, but user interaction required. |
| Affected versions | Google Chrome before 148.0.7778.179; Google release notes show 148.0.7778.178/179 on Windows/Mac and 148.0.7778.178 on Linux. Debian tracks affected Chromium packages across bullseye/bookworm/trixie branches. |
| Fixed versions | Google stable desktop update on 2026-05-19 shipped 148.0.7778.178/179. Debian backports include 148.0.7778.178-1~deb12u1 and 148.0.7778.178-1~deb13u1; later Debian security rollups also mark 148.0.7778.215-* as fixed. |
| Scanning / exposure data | *Inference:* Shodan/Censys/FOFA are poor measures here because this is a client-side browser flaw, not a network-listening service exposure problem. |
| Disclosure / reporting | Disclosed 2026-05-20; Google's release note says it was reported by Google on 2026-04-17. |
Sources.
Why this verdict
- Sandboxed renderer only: Google and NVD both state the result is code execution *inside a sandbox*. Starting from the vendor's
8.8, that is the biggest downward adjustment because it limits blast radius unless chained with a second bug. - User interaction required: This is
UI:R, so the attacker still needs a victim to render malicious content. That implies phishing, malvertising, or compromised-site delivery rather than direct reach into every endpoint. - Client-side, not internet-exposed infrastructure: There is no server socket to scan, spray, or mass-exploit the way you would with VPNs, firewalls, or public web apps. Real exposure depends on user behavior and browser version hygiene.
- Threat intel is quiet: No KEV listing, no public exploitation evidence found, and the supplied EPSS (
0.00022) is extremely low. That does not make the bug harmless, but it removes the urgency premium. - Still not LOW: Chrome is ubiquitous and the bug is remotely delivered with no auth and low complexity once a user hits the page. In a 10,000-host estate, even moderate user-driven reach means you still want broad patch compliance.
Why not higher?
This is not a higher bucket because the attack chain has two compounding brakes: user interaction and sandboxed-only code execution. Treating it like a full endpoint takeover would ignore the fact that the attacker still needs either a second vulnerability or a very specific post-exploitation objective inside the renderer.
Why not lower?
This is not lower because it is still a memory-corruption bug in a massively deployed browser with remote content delivery and no authentication requirement. Even without public exploitation, a well-resourced attacker can realistically target high-value users through normal browsing paths.
Crowdsourced verification payload.
Run this on the target endpoint or in your software-audit tooling. Invoke it with python3 check_cve_2026_9119.py to auto-detect Chrome/Chromium, or pass an explicit path such as python3 check_cve_2026_9119.py "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; no admin rights are normally required unless your EDR blocks process inspection.
#!/usr/bin/env python3
# check_cve_2026_9119.py
# Determine whether a local Chrome/Chromium binary is vulnerable to CVE-2026-9119.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')
FIXED_WINDOWS_MAC = (148, 0, 7778, 179)
FIXED_LINUX = (148, 0, 7778, 178)
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 cmp_ver(a, b):
return (a > b) - (a < b)
def candidates():
system = platform.system().lower()
c = []
if len(sys.argv) > 1:
c.append(sys.argv[1])
# PATH-based binaries
for name in [
'google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser',
'chrome', 'msedge' # included only so the script can tell you UNKNOWN/not-applicable if pointed there
]:
p = shutil.which(name)
if p:
c.append(p)
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 base:
for s in suffixes:
c.append(os.path.join(base, s))
elif system == 'darwin':
c.extend([
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium'
])
else:
c.extend([
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'/snap/bin/chromium'
])
# de-dup while preserving order
seen = set()
out = []
for item in c:
if item and item not in seen:
seen.add(item)
out.append(item)
return out
def get_version(binary):
try:
cp = subprocess.run([binary, '--version'], capture_output=True, text=True, timeout=10)
text = (cp.stdout or '') + ' ' + (cp.stderr or '')
return parse_version(text), text.strip()
except Exception:
return None, ''
def main():
system = platform.system().lower()
fixed = FIXED_LINUX if system == 'linux' else FIXED_WINDOWS_MAC
found_any = False
for binary in candidates():
if not os.path.exists(binary):
continue
found_any = True
ver, raw = get_version(binary)
if ver is None:
continue
# Basic product sanity check
lowered = raw.lower()
if 'edge' in lowered:
print(f'UNKNOWN: {binary} appears to be Microsoft Edge, not Chrome/Chromium ({raw})')
sys.exit(2)
status = 'PATCHED' if cmp_ver(ver, fixed) >= 0 else 'VULNERABLE'
print(f'{status}: {binary} version {ver[0]}.{ver[1]}.{ver[2]}.{ver[3]}')
sys.exit(0 if status == 'PATCHED' else 1)
if not found_any:
print('UNKNOWN: no Chrome/Chromium binary found; pass an explicit path as an argument')
else:
print('UNKNOWN: found candidate binary but could not parse a version')
sys.exit(2)
if __name__ == '__main__':
main()