This is peeking through a keyhole with a stopwatch, not kicking the door in
CVE-2026-11284 is a side-channel information disclosure bug in Chrome's PerformanceAPIs that affects Google Chrome versions before 149.0.7827.53. The attacker hosts a crafted web page, gets a user to load it, and then uses browser timing behavior to infer cross-origin data or state that normal web isolation rules should hide. That is materially different from RCE: there is no code execution, no sandbox escape, and no direct server compromise in the described impact.
The vendor's MEDIUM 6.5 baseline is defensible in a vacuum because the flaw is remotely triggerable and can hit confidentiality, but it overstates the practical enterprise urgency. Real exploitation requires a user to browse to attacker content, then depends on extracting useful cross-origin signal through timing noise, browser mitigations, and target-page behavior. That combination makes this a fleet hygiene issue, not an interrupt-everything patch emergency.
4 steps from start to impact.
Land the victim on attacker HTML
PerformanceObserver / timing APIs, consistent with the Chrome advisory text for this CVE and related Chrome timing leaks.- Target must run Chrome older than
149.0.7827.53 - Victim must browse to attacker-controlled or attacker-influenced content
- JavaScript must be allowed to run
- Requires user interaction; there is no wormable path
- Web filtering, ad blocking, secure web gateways, and basic phishing controls reduce reach
- Enterprise Chrome usually auto-updates, shrinking long-tail exposure
Probe cross-origin behavior with timing primitives
PerformanceAPIs. The technique is a side-channel, so the exploit depends on turning tiny timing differences into a reliable information signal rather than reading protected data directly.- Targeted web app or origin must expose measurable timing/state differences
- Browser mitigations must not fully drown or normalize the signal
- Modern browsers add noise, partition state, and constrain some high-resolution timing uses
- Many SaaS apps will not expose stable, high-value signals through this channel
- Network jitter and endpoint load degrade reliability in real user environments
PerformanceObserver usage, but coverage is inconsistent.Infer useful bits from noisy measurements
- Victim must stay on page long enough for repeated measurements
- The attacker's model must map timing patterns to real secrets or state
- Useful leakage is usually narrow and context-specific, not universal across all sites
- Users who close the page quickly or background the tab reduce signal quality
- CPU throttling, tab suspension, and browser power-saving features can break measurement fidelity
Exfiltrate inferred cross-origin data
- Outbound HTTPS from the browser must be allowed
- The inferred data must be meaningful enough to monetize or chain onward
- The blast radius is often limited to the browsing context and targeted web properties
- This is not a privilege-escalation or persistence mechanism
- No evidence found of active exploitation or turnkey criminal tooling
149.0.7827.53+ and that policy or VDI image drift is not pinning old builds. For a LOW verdict there is no mitigation SLA; treat this as backlog hygiene and close gaps through normal endpoint management.- A WAF does not meaningfully solve this because the vulnerable component is the client browser, not your web server.
- MFA helps protect accounts broadly but does not stop timing-based inference of cross-origin state once the victim is already browsing in-session.
- Network perimeter blocking alone is weak here because the malicious page and exfil traffic can look like ordinary HTTPS browsing.
The supporting signals.
| In-the-wild status | No evidence found of active exploitation as of 2026-06-05/06, and the CVE is not listed in CISA KEV. |
|---|---|
| Public PoC availability | No public PoC located in current web/GitHub search results for CVE-2026-11284; exploitation would likely require bespoke JavaScript tuned to the target site. |
| EPSS | 0.00028 (~0.028%) per user-supplied intel, which is extremely low modeled near-term exploitation probability. |
| KEV status | Not KEV-listed. That is a strong downward signal for enterprise urgency because CISA is not seeing enough real-world abuse to elevate it. |
| CVSS vector interpretation | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N means remote delivery and no privileges, but user interaction is mandatory and the impact is confidentiality-only. In practice, C:H on a browser side channel often overstates what most enterprises will actually lose. |
| Affected versions | Google Chrome prior to 149.0.7827.53. For operations teams, that means your exposure population is the set of endpoints that missed normal browser auto-update. |
| Fixed versions | Patch level is 149.0.7827.53 or later; Chrome early stable shipped 149.0.7827.53/.54 for Windows/Mac, and Chromium downstreams such as openSUSE list fixes in their Chromium 149 update. |
| Scanning / exposure data | Traditional internet exposure data from Shodan/Censys/FOFA is mostly not meaningful here because this is a client-side browser flaw, not a server product you can census from the edge. Exposure is driven by endpoint version drift and user browsing, not by an open port. |
| Disclosure date | 2026-06-05. |
| Reporter / researcher | No clear public researcher attribution found in currently indexed advisory material. Treat the reporting party as not publicly attributed yet. |
Sources.
- Chrome Releases - Early Stable Update for Desktop (149.0.7827.53/.54)
- Chrome for Testing availability - Stable 149.0.7827.53
- openSUSE Chromium patchinfo listing CVE-2026-11284
- CISA Known Exploited Vulnerabilities Catalog
- FIRST EPSS overview
- FIRST EPSS API documentation
- CWE-1300: Improper Protection of Physical Side Channels
- VulDB entry summarizing CVE-2026-11284 and Chromium severity note
Why this verdict
- User interaction drags this down: the attacker needs the victim to load a crafted page, which implies a lure or prior traffic-manipulation stage rather than direct target compromise.
- It is a side-channel, not a memory-corruption path: no RCE, no sandbox escape, no local privilege escalation, and no server-side compromise are in scope.
- Reachable population is broad, but weaponizable population is narrower: Chrome is everywhere, yet only endpoints still below
149.0.7827.53and visiting attacker content are exposed, and useful leakage depends on target-site behavior. - Modern controls add real friction: secure web gateways, ad/phishing controls, browser auto-update, site isolation hardening, and endpoint/browser throttling all erode reliability.
- Threat intel is quiet: no KEV listing, no active exploitation evidence found, and an EPSS of
0.00028provide strong downward pressure from the vendor baseline.
Why not higher?
If this were a no-click browser RCE or a renderer-to-sandbox escape, this would jump several buckets. Instead, the attacker gets at most a confidentiality leak through noisy timing inference, and only after successfully luring a victim into a vulnerable browser session. That is not the attack path that burns down an enterprise on first contact.
Why not lower?
It is still a remotely delivered browser bug in one of the most widely deployed endpoint applications in the fleet. A well-targeted campaign against high-value users could still use a malicious page to infer sensitive cross-origin state or data, so writing it off entirely would be complacent.
Crowdsourced verification payload.
Run this on the target endpoint or through your EDR/remote-exec tool. Invoke it as python3 check_chrome_cve_2026_11284.py on macOS/Linux or py check_chrome_cve_2026_11284.py on Windows; no admin rights are required for basic version discovery, though registry/file access on locked-down Windows builds may work better with standard user context than with some service accounts.
#!/usr/bin/env python3
# check_chrome_cve_2026_11284.py
# Detects whether local Google Chrome / Chromium is below 149.0.7827.53.
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
FIXED = (149, 0, 7827, 53)
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 cmp_ver(a, b):
return (a > b) - (a < b)
def run_cmd(cmd):
try:
p = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
out = (p.stdout or '') + ' ' + (p.stderr or '')
return out.strip()
except Exception:
return ''
def candidate_paths():
system = platform.system().lower()
paths = []
if system == 'windows':
local = os.environ.get('LOCALAPPDATA', '')
pf = os.environ.get('PROGRAMFILES', '')
pf86 = os.environ.get('PROGRAMFILES(X86)', '')
paths += [
os.path.join(local, 'Google', 'Chrome', 'Application', 'chrome.exe'),
os.path.join(pf, 'Google', 'Chrome', 'Application', 'chrome.exe'),
os.path.join(pf86, 'Google', 'Chrome', 'Application', 'chrome.exe'),
os.path.join(local, 'Chromium', 'Application', 'chrome.exe'),
os.path.join(pf, 'Chromium', 'Application', 'chrome.exe'),
os.path.join(pf86, 'Chromium', 'Application', 'chrome.exe'),
]
elif system == 'darwin':
paths += [
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
'/Applications/Chromium.app/Contents/MacOS/Chromium',
os.path.expanduser('~/Applications/Chromium.app/Contents/MacOS/Chromium'),
]
else:
paths += [
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'/snap/bin/chromium',
'/opt/google/chrome/chrome',
]
return paths
def windows_registry_version():
reg_queries = [
['reg', 'query', r'HKLM\Software\Google\Chrome\BLBeacon', '/v', 'version'],
['reg', 'query', r'HKCU\Software\Google\Chrome\BLBeacon', '/v', 'version'],
['reg', 'query', r'HKLM\Software\Chromium\BLBeacon', '/v', 'version'],
['reg', 'query', r'HKCU\Software\Chromium\BLBeacon', '/v', 'version'],
]
for q in reg_queries:
out = run_cmd(q)
v = parse_version(out)
if v:
return ('registry', v)
return None
def discover_versions():
found = []
seen = set()
# PATH binaries first
for name in ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']:
full = shutil.which(name)
if full and full not in seen:
seen.add(full)
out = run_cmd([full, '--version'])
v = parse_version(out)
if v:
found.append((full, v))
# Platform paths
for p in candidate_paths():
if os.path.exists(p) and p not in seen:
seen.add(p)
out = run_cmd([p, '--version'])
v = parse_version(out)
if v:
found.append((p, v))
# Windows registry fallback
if platform.system().lower() == 'windows':
rv = windows_registry_version()
if rv:
found.append(rv)
return found
def fmt(v):
return '.'.join(str(x) for x in v)
def main():
results = discover_versions()
if not results:
print('UNKNOWN: Chrome/Chromium version not found on this host')
sys.exit(2)
vulnerable = []
patched = []
for loc, ver in results:
if cmp_ver(ver, FIXED) < 0:
vulnerable.append((loc, ver))
else:
patched.append((loc, ver))
# If any installed browser instance is below fixed version, call host vulnerable.
if vulnerable:
details = '; '.join([f'{loc}={fmt(ver)}' for loc, ver in vulnerable])
print(f'VULNERABLE: found Chrome/Chromium below {fmt(FIXED)} -> {details}')
sys.exit(1)
details = '; '.join([f'{loc}={fmt(ver)}' for loc, ver in patched])
print(f'PATCHED: all discovered Chrome/Chromium versions are >= {fmt(FIXED)} -> {details}')
sys.exit(0)
if __name__ == '__main__':
main()