Like finding a side door already inside the building, not kicking in the front gate
CVE-2026-10977 is an uninitialized-use bug in Skia in Google Chrome that affects builds before 149.0.7827.53; Google's stable update shipped 149.0.7827.53 on Linux and 149.0.7827.53/54 on Windows and Mac. The bug lets an attacker leak cross-origin data through a crafted HTML page, but the description matters more than the weakness class: exploitation requires the attacker to have already compromised the renderer process.
That prerequisite makes the vendor-style 6.5 / MEDIUM baseline too generous for enterprise patch triage. In real deployments this is not an initial-access browser RCE; it is a post-renderer-compromise data-theft primitive with confidentiality impact only, no sandbox escape, no host code execution, no integrity change, and no evidence of active exploitation.
4 steps from start to impact.
Land a separate renderer exploit
- Victim uses vulnerable Chrome before 149.0.7827.53
- Attacker can get the victim to load malicious browser content
- Attacker has a separate renderer-compromise primitive
- This is the biggest brake on severity: it assumes prior compromise of a browser sandboxed process
- Modern browser exploit mitigations, site isolation, EDR, and exploit prevention can break the chain before this CVE matters
- No public PoC for this CVE was located
Trigger the Skia uninitialized-use path
- Compromised renderer can execute attacker-controlled page logic
- Victim reaches a page that exercises the vulnerable Skia path
- Bug details remain restricted in Chromium issue tracking
- Reliability may vary across GPU/OS/rendering combinations
- Browser auto-update shrinks the reachable population quickly
Read cross-origin data from renderer memory
- Sensitive cross-origin material is present or reachable in the renderer context
- The victim is authenticated to targets worth stealing from
- Impact depends on what the victim currently has open and authenticated
- This does not itself escape the sandbox or alter host state
- Some enterprise browsing patterns reduce sensitive cross-origin exposure
Exfiltrate the stolen data
- Outbound web access is available
- Recovered data is valuable enough to operationalize
- Enterprise proxies, CASB, DLP, and session protections can reduce downstream value
- Stolen material may be short-lived or bound to device/context
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found, and not listed in CISA KEV. |
|---|---|
| Public PoC | No public PoC repo or researcher write-up located. The Chromium issue is present but details appear restricted, which is normal for fresh Chrome fixes. |
| EPSS | 0.035% (11th percentile) per GitHub's FIRST-backed EPSS display — extremely low near-term exploitation probability. |
| KEV status | Absent from KEV as checked against the CISA catalog. No KEV date applies. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N maps to confidentiality-only impact with required user interaction. The vector still understates a key real-world prerequisite: the description itself says the attacker must have already compromised the renderer process. |
| Affected versions | Google Chrome before 149.0.7827.53; NVD records the vulnerable CPE as versions up to, but excluding, 149.0.7827.53. |
| Fixed versions | Chrome stable update shipped 149.0.7827.53 on Linux and 149.0.7827.53/54 on Windows/Mac. No distro-backport signal was identified in the sources; this is primarily a browser self-update story. |
| Exposure reality | This is a client-side browser flaw, not a routable service. There is no meaningful Shodan/Censys/FOFA external-surface count for the CVE itself; your exposure is the number of managed Chrome endpoints and unmanaged BYOD browsers. |
| Disclosure timeline | Chrome stable fix published 2026-06-02; NVD shows the CVE received 2026-06-04 and modified 2026-06-05; GitHub Advisory published 2026-06-05. |
| Reporter / source org | Chrome release notes say this issue was reported by Google on 2026-05-14 and tracked as Chromium issue 513340227. |
noisgate verdict.
The decisive factor is the renderer-compromise requirement in the CVE description. That turns this from an initial-access browser bug into a second-stage same-origin-bypass helper, which materially narrows the reachable attacker population and the number of real-world chains where it matters.
Why this verdict
- Renderer compromise is the real gate: the CVE text requires an attacker who has *already* compromised the renderer process, so I cut hard from the 6.5 baseline because this is post-initial-access inside the browser, not a front-door bug.
- Reachable population is narrower than 'all Chrome users': Chrome is everywhere, but only the subset of victims hit by a separate renderer exploit and then steered into a tailored HTML path are actually exposed to this CVE's impact.
- Blast radius is confidentiality-only: the outcome is cross-origin data leakage, not sandbox escape, persistence, integrity change, or host takeover, which keeps the business impact materially below typical browser RCE chains.
Why not higher?
It is not higher because this CVE does not give the attacker their initial foothold; it assumes one. There is also no KEV listing, no public exploitation evidence, and the impact stops at data disclosure from the browser context rather than code execution or OS compromise.
Why not lower?
It is not lower because browsers are ubiquitous and cross-origin leakage can still expose tokens, authenticated content, and internal web app data once chained. For high-value users already targeted with browser exploitation, this is still a useful post-compromise primitive worth tracking.
What to do — in priority order.
- Enforce browser auto-update — Make sure managed Chrome channels are allowed to self-update or receive your normal endpoint software deployment package. For a LOW verdict there is no mitigation SLA; treat this as backlog hygiene and keep it inside your standard browser maintenance motion.
- Prioritize high-risk browsing cohorts — Apply extra scrutiny to admins, finance users, developers, and anyone who routinely handles privileged SaaS sessions, because cross-origin leakage is only valuable when the victim has valuable authenticated browser state. For this LOW call, do this in the normal patch cycle rather than as an emergency action.
- Harden the precondition — Because the real choke point is the separate renderer compromise, invest in exploit protection, extension control, browser isolation for risky workflows, and rapid patching of true browser RCEs. That does more to reduce risk from this CVE than any narrow compensating control aimed at Skia itself.
- Audit unmanaged browser exposure — Find BYOD, VDI golden images, kiosk systems, and stale software repositories where Chrome may lag behind the fixed builds. For a LOW verdict there is no special deadline, but closing those blind spots keeps minor browser issues from lingering indefinitely.
- A WAF does not meaningfully help; exploitation happens inside the local browser after page render, not against your server-side application tier.
- MFA does not prevent the data leak itself; if authenticated browser content or tokens are exposed cross-origin, MFA has already been satisfied.
- Network IDS signatures are weak here because the exploit path is client-side and exfiltration can ride ordinary HTTPS traffic.
Crowdsourced verification payload.
Run this on the target endpoint or through your software inventory agent with a local Python 3 interpreter; no admin rights are required if Chrome is in a standard install path. Example: python3 check_chrome_cve_2026_10977.py on macOS/Linux or py check_chrome_cve_2026_10977.py on Windows. The script checks common Chrome executable locations, runs --version, and prints VULNERABLE, PATCHED, or UNKNOWN.
#!/usr/bin/env python3
# check_chrome_cve_2026_10977.py
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import os
import platform
import re
import shutil
import subprocess
import sys
from typing import Optional, Tuple, List
FIXED = (149, 0, 7827, 53)
COMMON_PATHS = {
"Windows": [
r"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
r"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
os.path.expandvars(r"%LOCALAPPDATA%\\Google\\Chrome\\Application\\chrome.exe"),
],
"Darwin": [
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
os.path.expanduser("~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"),
],
"Linux": [
"/usr/bin/google-chrome",
"/usr/bin/google-chrome-stable",
"/opt/google/chrome/google-chrome",
"/snap/bin/chromium",
"/usr/bin/chromium",
"/usr/bin/chromium-browser",
],
}
def parse_version(text: str) -> Optional[Tuple[int, int, int, int]]:
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_ge(a: Tuple[int, int, int, int], b: Tuple[int, int, int, int]) -> bool:
return a >= b
def run_version(path: str) -> Optional[str]:
try:
cp = subprocess.run([path, "--version"], capture_output=True, text=True, timeout=10)
out = (cp.stdout or "") + " " + (cp.stderr or "")
return out.strip()
except Exception:
return None
def candidate_paths() -> List[str]:
system = platform.system()
paths = []
if system == "Windows":
for name in ["chrome", "chrome.exe"]:
p = shutil.which(name)
if p:
paths.append(p)
else:
for name in ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]:
p = shutil.which(name)
if p:
paths.append(p)
for p in COMMON_PATHS.get(system, []):
if p and p not in paths:
paths.append(p)
# Deduplicate while preserving order
seen = set()
result = []
for p in paths:
if p not in seen:
seen.add(p)
result.append(p)
return result
def main() -> int:
found_any = False
checked = []
for path in candidate_paths():
if not path or not os.path.exists(path):
continue
found_any = True
output = run_version(path)
checked.append((path, output))
if not output:
continue
ver = parse_version(output)
if not ver:
continue
print(f"Detected browser: {path}")
print(f"Reported version: {'.'.join(map(str, ver))}")
print(f"Fixed threshold for CVE-2026-10977: {'.'.join(map(str, FIXED))}")
if version_ge(ver, FIXED):
print("PATCHED")
return 0
else:
print("VULNERABLE")
return 1
if not found_any:
print("UNKNOWN")
print("Reason: No Chrome/Chromium executable found in common locations or PATH.")
return 2
print("UNKNOWN")
print("Reason: Browser executable found, but version could not be determined.")
for path, output in checked:
print(f"Checked: {path} -> {repr(output)}")
return 2
if __name__ == "__main__":
sys.exit(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.