This is a cracked interior door, not the front gate
CVE-2026-11121 is an input-validation flaw in Chrome's Skia graphics component that affects Google Chrome versions earlier than 149.0.7827.53 on Linux and 149.0.7827.53/.54 on Windows and macOS. Per the published CNA description, the bug lets an attacker who has already compromised the renderer process leak cross-origin data through a crafted HTML page.
Reality check: this is not an initial-access browser RCE, and it is not a sandbox escape. The decisive friction is the prerequisite attacker position: they must already own the renderer, which makes this a second-stage chain component with narrow standalone utility. Google's own Chromium severity label of *Medium* matches the operational reality.
4 steps from start to impact.
Land the user on attacker-controlled content
- Chrome version is earlier than
149.0.7827.53 - Target user browses attacker-controlled or attacker-influenced content
- The page reaches the affected Skia path
- This CVE does not produce impact from page load alone
- Many enterprise users never hit the exact rendering path needed
- Web filtering and URL isolation can reduce delivery opportunities
Compromise the renderer first with a separate bug or malicious extension
- Attacker has a working renderer-compromise primitive outside this CVE
- That primitive survives modern Chrome hardening long enough to run follow-on logic
- This is the biggest downward pressure on severity: the attacker is already past the initial exploit hurdle
- EDR, browser exploit mitigations, extension allowlisting, and rapid Chrome auto-update all raise the bar
Abuse Skia validation to break cross-origin isolation
- Renderer is already under attacker influence
- Victim has interesting authenticated web content loaded or reachable in-session
- Impact is confined to data leakage, not arbitrary native code execution
- The attacker still needs valuable browser-resident material to steal
Exfiltrate session data and pivot to apps
- The browser session contains reusable secrets or sensitive data
- Exfiltrated material is valuable enough to support follow-on access
- Many modern apps bind sessions to device posture, IP reputation, or re-auth triggers
- Short-lived tokens and strong conditional access reduce replay value
Perimeter vulnerability scanningdoes not help much because there is no server-side listening service to fingerprint; this is an endpoint browser-version problem.WAF rulesdo not materially stop a local browser renderer already under attacker influence from abusing the client-side flaw.Password resets alonemiss the likely impact path if the attacker steals active session data or cookies rather than credentials.
The supporting signals.
| In-the-wild status | No evidence found that CVE-2026-11121 is in CISA KEV, and I found no vendor statement or credible reporting indicating active exploitation as of 2026-06-05. |
|---|---|
| Public PoC availability | No public exploit or proof-of-concept was found in the authoritative/vendor-facing sources reviewed. That fits the bug shape: it is a chain component, not a clean standalone exploit target. |
| EPSS | User-supplied EPSS is 0.00047, which is extremely low. I could not confirm an authoritative percentile from the sources reviewed, but this score is consistent with low standalone exploitation interest. |
| KEV status | Not KEV-listed. That matters because Chrome issues that become operational fire drills usually show either KEV inclusion, vendor zero-day language, or both. |
| Vendor severity baseline | There is no vendor CVSS score and no official CVSS vector published, but Chrome's release notes and CNA text label the flaw as Chromium security severity: Medium. |
| Affected versions | Google's CNA record marks Chrome < 149.0.7827.53 as affected. The desktop stable note shows 149.0.7827.53 for Linux and 149.0.7827.53/.54 for Windows and macOS. |
| Fixed versions | Upgrade desktop Chrome to Linux 149.0.7827.53 or Windows/macOS 149.0.7827.53/.54 or later. This is a browser-binary fix; there is no distro-specific backport evidence in the sources reviewed. |
| Exposure and scanning reality | Internet-wide exposure tools like *Shodan*, *Censys*, and *FOFA* are mostly irrelevant here because this is a client-side browser flaw, not a remotely enumerable network service. Your real exposure count is your managed endpoint fleet running pre-149 Chrome. |
| Disclosure and reporter | The CVE record was published on 2026-06-04. Google's stable release notes list the issue as reported by Google on 2026-04-10, issue 501483855. |
| Chain context | This shipped in a Chrome 149 batch containing many Critical and High bugs, including initial-compromise browser flaws. That context matters: CVE-2026-11121 is more useful as a follow-on privacy bypass after another bug lands. |
Sources.
Why this verdict
- Major downward adjustment: requires a compromised renderer first. That implies the attacker is already past the hard part of the browser kill chain.
- Impact is confidentiality only. The published description is cross-origin data leakage, not code execution, privilege escalation, or sandbox escape.
- Exposure is broad but not directly reachable. Chrome is everywhere, but the reachable population for this exact bug is only the subset where an attacker can first land a renderer compromise and then chain successfully.
Why not higher?
It is not a higher-severity issue because it does not provide initial code execution, does not escape the sandbox, and does not require defenders to assume internet-reachable unauthenticated exploitation. The attacker position requirement compounds sharply: internal-to-browser post-compromise plus a data-theft-only outcome is not a patch-everything-now event.
Why not lower?
It is not lower because cross-origin data leakage inside a live enterprise browser session can still expose SSO-backed application data, tokens, and sensitive content. Chrome is widely deployed, and post-renderer chain components matter when paired with other browser bugs or malicious extensions.
Crowdsourced verification payload.
Run this on the target endpoint or through your EDR live-response/remote script runner. Invoke it with python3 check_cve_2026_11121.py on macOS/Linux or py check_cve_2026_11121.py on Windows; no admin rights are usually required, but the script needs permission to read common install paths and execute the browser binary with --version.
#!/usr/bin/env python3
# check_cve_2026_11121.py
# Determine whether installed Chrome/Chromium builds are vulnerable to CVE-2026-11121.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
from pathlib import Path
FIXED = (149, 0, 7827, 53)
CANDIDATES = {
'Windows': [
r'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
r'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
r'C:\\Users\\%USERNAME%\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe',
r'C:\\Program Files\\Chromium\\Application\\chrome.exe',
r'C:\\Program Files (x86)\\Chromium\\Application\\chrome.exe'
],
'Darwin': [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
str(Path.home() / 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
'/Applications/Chromium.app/Contents/MacOS/Chromium'
],
'Linux': [
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/opt/google/chrome/chrome',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'/snap/bin/chromium'
]
}
EXE_FALLBACKS = ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']
def parse_version(text):
m = re.search(r'(\d+)\.(\d+)\.(\d+)\.(\d+)', text)
if not m:
return None
return tuple(int(x) for x in m.groups())
def version_lt(a, b):
return a < b
def expand_win(path):
return os.path.expandvars(path.replace('%USERNAME%', os.environ.get('USERNAME', '')))
def collect_paths():
system = platform.system()
paths = []
for p in CANDIDATES.get(system, []):
paths.append(expand_win(p) if system == 'Windows' else p)
for name in EXE_FALLBACKS:
resolved = shutil.which(name)
if resolved:
paths.append(resolved)
seen = []
for p in paths:
if p and p not in seen:
seen.append(p)
return seen
def get_version(binary):
try:
proc = subprocess.run([binary, '--version'], capture_output=True, text=True, timeout=8)
output = (proc.stdout or '') + ' ' + (proc.stderr or '')
return parse_version(output)
except Exception:
return None
def main():
found = []
vulnerable = []
patched = []
for path in collect_paths():
if os.path.isfile(path) or shutil.which(path):
ver = get_version(path)
if ver:
found.append((path, ver))
if version_lt(ver, FIXED):
vulnerable.append((path, ver))
else:
patched.append((path, ver))
if vulnerable:
print('VULNERABLE')
for path, ver in vulnerable:
print(f'{path} -> {".".join(map(str, ver))} < {".".join(map(str, FIXED))}')
sys.exit(1)
if patched:
print('PATCHED')
for path, ver in patched:
print(f'{path} -> {".".join(map(str, ver))}')
sys.exit(0)
print('UNKNOWN')
print('No runnable Chrome/Chromium binary found in common locations, or version parsing failed.')
sys.exit(2)
if __name__ == '__main__':
main()