← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-10985 · CWE-125 · Disclosed 2026-06-04

Out of bounds read in Skia in Google Chrome prior to 149

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a peephole drilled through Chrome’s same-origin wall, not a front door kicked off its hinges

CVE-2026-10985 is an out-of-bounds read in Chrome’s Skia graphics stack that affects Google Chrome versions prior to 149.0.7827.53. A malicious site can use crafted HTML to trigger the bug and leak data that should stay isolated by browser origin boundaries, turning a page view into cross-origin information disclosure rather than full browser compromise.

The vendor-style 6.5 MEDIUM label is mostly fair for enterprise patch triage. Chrome is everywhere, so the reachable population is huge, but the attacker still needs the user to render hostile content and the outcome is confidentiality loss only; there is no published claim here of code execution, sandbox escape, or system takeover. That keeps this out of emergency territory even though Chrome’s internal bug label calls the issue High.

"A real browser data-leak bug, but it still needs a lure and it stops short of code execution."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land the victim on attacker-controlled HTML

The weapon is a custom HTML/JavaScript lure page; no public exploit kit or GitHub PoC was located as of 2026-06-05. The attacker needs the user to browse to a page, ad frame, or embedded content path that renders the crafted payload in vulnerable Chrome.
Conditions required:
  • Target is running Chrome earlier than 149.0.7827.53
  • User interaction occurs: click, redirect, ad-tech delivery, or embedded content render
  • Attacker can host or inject crafted web content
Where this breaks in practice:
  • Requires user interaction; this is not scan-and-own
  • Enterprise web filtering, ad blocking, and browser isolation can reduce lure success
  • Short browser update cadences shrink the exploitable window fast
Detection/coverage: Traditional network scanners do not prove exploitability here. Version inventory from EDR, MDM, SCCM, Intune, or package management is the reliable coverage point.
STEP 02

Trigger the Skia out-of-bounds read

The lure page drives Skia into reading beyond intended memory bounds while processing crafted HTML-rendering content. The practical weapon is a page-level renderer trigger rather than a network service exploit, so exploitation lives inside the browser process after content is rendered.
Conditions required:
  • Renderer reaches the vulnerable Skia code path
  • Exploit content is stable enough across the victim’s platform/build
Where this breaks in practice:
  • Browser exploitation reliability is sensitive to exact build, platform, and memory layout
  • The underlying Chromium issue is not publicly readable from the available source set, which suggests lower public exploit maturity right now
Detection/coverage: Exploit prevention telemetry may show renderer crashes or anomalous browser terminations, but many info-leak attempts will look like normal page rendering.
STEP 03

Harvest cross-origin data from browser memory

If successful, the attacker leaks data that should be blocked by same-origin boundaries. In practice that means the value comes from what the victim is already authenticated to or currently viewing in the same browser context, not from arbitrary host takeover.
Conditions required:
  • Victim has useful browser-resident secrets or active authenticated sessions
  • Leaked bytes are sufficient to recover tokens, page fragments, or sensitive cross-origin content
Where this breaks in practice:
  • Impact depends heavily on what the victim is signed into at that moment
  • This is confidentiality-only in the published record; no integrity or availability impact is claimed
  • Blast radius is usually one browser session at a time
Detection/coverage: There is no clean signature for the data leak itself. Detection is mostly indirect: suspicious outbound requests from the lure domain, user-reported odd browser behavior, and browser telemetry correlations.
STEP 04

Operationalize stolen session data

The follow-on tool is whatever reuses the leaked data: session replay scripts, token theft workflows, or targeted phishing against internal web apps. This is where business risk can jump, but only if the leaked material is actually reusable.
Conditions required:
  • Leaked data contains actionable secrets or sensitive internal content
  • Attacker can use the data before tokens expire or sessions rotate
Where this breaks in practice:
  • Modern session binding, short-lived tokens, and MFA-backed reauth can limit replay value
  • Many browser leaks produce partial data, not turnkey account takeover
Detection/coverage: Downstream abuse may be visible in IdP logs, impossible-travel/session anomalies, or unusual access to internal web apps. The browser flaw itself is rarely what defenders catch first.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo authoritative exploitation evidence found as of 2026-06-05. The CVE is not in CISA KEV, and the source set reviewed did not show Google calling this a zero-day.
PoC availabilityNo public GitHub or researcher PoC located in web review as of 2026-06-05. The referenced Chromium issue exists, but the accessible issue page did not expose technical details without sign-in.
EPSS0.00035 from the user intel, which is extremely low in absolute terms; that aligns with low near-term exploitation pressure rather than internet-scale abuse.
KEV statusNot KEV-listed as of 2026-06-05. That materially lowers urgency versus browser bugs already showing real-world abuse.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N maps to drive-by reachable, no auth, user interaction required, confidentiality-only impact.
Affected versionsGoogle Chrome prior to 149.0.7827.53 per NVD and the advisory chain. GovCERT also summarizes the affected set as versions before 149.0.7827.53.
Fixed versionsPatch floor is 149.0.7827.53. Google’s release note URL indicates the stable desktop rollout at 149.0.7827.53/.54; for conservative fleet triage, treat anything below 149.0.7827.53 as vulnerable.
Exposure and scanning realityThis is not an internet-scannable service; Shodan/Censys/FOFA-style exposure counts are not a useful prioritization input here. The real exposure metric is how many endpoints are still on old Chrome builds.
Disclosure date2026-06-04 in NVD quick info, with modification on 2026-06-05 after CISA-ADP scoring.
Reporter / provenanceThe CNA/source is Chrome. No public researcher credit was recoverable from the accessible source set, so assume the detail remains limited at this stage.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to MEDIUM (6.8/10)

The decisive factor is that the exploit chain still requires user-driven rendering of attacker content and only delivers information disclosure, not code execution or sandbox escape. Chrome’s massive footprint keeps this relevant, but the lack of active exploitation evidence and the confidentiality-only outcome keep it in MEDIUM.

HIGH Affected version floor and fixed version threshold
MEDIUM Exploitability in real enterprise browsing scenarios
LOW Public exploit maturity, because the linked Chromium issue is not readable from the accessible source set

Why this verdict

  • Start from the browser baseline: Chrome is near-ubiquitous in enterprise fleets, so any remotely triggerable browser bug deserves initial attention even before exploitation evidence shows up.
  • User interaction is a real brake: the attacker must get the victim to render crafted content, which implies phishing, malvertising, or content injection rather than unauthenticated internet-wide exploitation.
  • Impact is bounded to confidentiality: the published record claims cross-origin data leakage, not arbitrary code execution, persistence, lateral movement, or OS compromise; that sharply limits blast radius per event.
  • No live-fire signal: no KEV entry, no zero-day language in the reviewed sources, and a very low EPSS all push this down from emergency patch status.
  • Population is wide but exploit surface is session-dependent: the bug matters most when users are simultaneously authenticated to valuable internal or SaaS apps, which is common enough to matter but not enough to justify a HIGH without stronger exploitation evidence.

Why not higher?

A HIGH would need either an exploitation amplifier or a bigger blast radius: active attacks, public exploit tooling, code execution, sandbox escape, or a practical path to broad credential theft at scale. We do not have that here from the reviewed sources; what we have is a browser info leak that still depends on a lure and on valuable victim browsing state.

Why not lower?

This is not backlog lint. It is remotely reachable through normal web browsing, requires no authentication, and targets a product that exists on nearly every enterprise endpoint. Cross-origin leakage in a business browser can still expose internal app data, tokens, or sensitive page content, so LOW would understate the risk.

05 · Compensating Control

What to do — in priority order.

  1. Force browser relaunch compliance — Make sure auto-updated Chrome actually exits and relaunches so the fixed build is loaded. For a MEDIUM finding there is no mitigation SLA, so use this as a low-friction interim control while completing remediation inside the 365-day window.
  2. Tighten risky-web-content filtering — Reduce successful lure delivery through web filtering, DNS filtering, ad blocking, and browser isolation for high-risk user groups. There is no mitigation SLA for this severity, so treat it as targeted risk reduction rather than emergency containment.
  3. Prioritize high-value users first — Patch executives, admins, finance, and developers first because the value of a browser info leak scales with the sensitivity of the sites and sessions they hold. Even without a mitigation SLA, that ordering materially lowers business risk while the broader fleet rolls forward.
  4. Inventory Chrome by exact version — Query the fleet for Chrome versions below 149.0.7827.53 and use that list to drive cleanup, because network exposure scanners will not help much here. For MEDIUM, there is no mitigation SLA — go straight to the 365-day remediation window, but you should still close the visibility gap immediately.
What doesn't work
  • Perimeter vulnerability scanning does not meaningfully measure exposure here; this is endpoint/browser version risk, not a listening service.
  • Relying on auto-update alone does not fully solve it if users never restart Chrome; the vulnerable code stays resident until relaunch.
  • Classic WAF rules do not protect users browsing the public internet from a malicious page rendered locally in the browser.
06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or via your software-distribution/EDR scripting channel, not from an auditor workstation. Invoke it with python3 check_chrome_cve_2026_10985.py; no admin rights are required in most cases, though Windows registry reads may work best under the local user or standard endpoint agent context. It checks common Chrome locations on Windows, macOS, and Linux and prints VULNERABLE, PATCHED, or UNKNOWN.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# Check Google Chrome version exposure for CVE-2026-10985
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=ERROR

import os
import platform
import plistlib
import re
import shutil
import subprocess
import sys

MIN_VERSION = (149, 0, 7827, 53)


def parse_version(v):
    if not v:
        return None
    m = re.findall(r"\d+", str(v))
    if len(m) < 4:
        return None
    return tuple(int(x) for x in m[:4])


def cmp_version(a, b):
    return (a > b) - (a < b)


def run_cmd(cmd):
    try:
        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=10)
        if p.returncode == 0:
            return p.stdout.strip()
    except Exception:
        pass
    return None


def get_windows_version():
    # Prefer registry beacon values used by Chrome installers.
    try:
        import winreg
    except Exception:
        return None

    reg_paths = [
        (winreg.HKEY_CURRENT_USER, r"Software\Google\Chrome\BLBeacon", "version"),
        (winreg.HKEY_LOCAL_MACHINE, r"Software\Google\Chrome\BLBeacon", "version"),
        (winreg.HKEY_LOCAL_MACHINE, r"Software\WOW6432Node\Google\Chrome\BLBeacon", "version"),
        (winreg.HKEY_CURRENT_USER, r"Software\Chromium\BLBeacon", "version"),
        (winreg.HKEY_LOCAL_MACHINE, r"Software\Chromium\BLBeacon", "version"),
    ]
    for hive, path, name in reg_paths:
        try:
            with winreg.OpenKey(hive, path) as k:
                value, _ = winreg.QueryValueEx(k, name)
                if value:
                    return value
        except Exception:
            continue

    # Fallback to executable version if available.
    possible = [
        os.path.join(os.environ.get("ProgramFiles", r"C:\Program Files"), "Google", "Chrome", "Application", "chrome.exe"),
        os.path.join(os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)"), "Google", "Chrome", "Application", "chrome.exe"),
    ]
    for exe in possible:
        if os.path.exists(exe):
            try:
                import win32api  # type: ignore
                info = win32api.GetFileVersionInfo(exe, "\\")
                ms = info['FileVersionMS']
                ls = info['FileVersionLS']
                return f"{ms >> 16}.{ms & 0xFFFF}.{ls >> 16}.{ls & 0xFFFF}"
            except Exception:
                continue
    return None


def get_macos_version():
    plist_paths = [
        "/Applications/Google Chrome.app/Contents/Info.plist",
        os.path.expanduser("~/Applications/Google Chrome.app/Contents/Info.plist"),
        "/Applications/Chromium.app/Contents/Info.plist",
        os.path.expanduser("~/Applications/Chromium.app/Contents/Info.plist"),
    ]
    for p in plist_paths:
        if os.path.exists(p):
            try:
                with open(p, "rb") as f:
                    data = plistlib.load(f)
                for key in ("KSVersion", "CFBundleShortVersionString", "CFBundleVersion"):
                    if data.get(key):
                        return str(data[key])
            except Exception:
                continue

    binaries = [
        "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
        "/Applications/Chromium.app/Contents/MacOS/Chromium",
    ]
    for b in binaries:
        if os.path.exists(b):
            out = run_cmd([b, "--version"])
            if out:
                return out
    return None


def get_linux_version():
    candidates = [
        "google-chrome",
        "google-chrome-stable",
        "chromium-browser",
        "chromium",
    ]
    for cmd in candidates:
        full = shutil.which(cmd)
        if full:
            out = run_cmd([full, "--version"])
            if out:
                return out
    return None


def main():
    system = platform.system().lower()
    version_raw = None

    if "windows" in system:
        version_raw = get_windows_version()
    elif "darwin" in system:
        version_raw = get_macos_version()
    elif "linux" in system:
        version_raw = get_linux_version()
    else:
        print("UNKNOWN: unsupported platform")
        sys.exit(2)

    parsed = parse_version(version_raw)
    if not parsed:
        print("UNKNOWN: Chrome version not found")
        sys.exit(2)

    if cmp_version(parsed, MIN_VERSION) < 0:
        print(f"VULNERABLE: detected Chrome/Chromium version {'.'.join(map(str, parsed))} < {'.'.join(map(str, MIN_VERSION))}")
        sys.exit(1)
    else:
        print(f"PATCHED: detected Chrome/Chromium version {'.'.join(map(str, parsed))} >= {'.'.join(map(str, MIN_VERSION))}")
        sys.exit(0)


if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"UNKNOWN: error during check: {e}")
        sys.exit(3)
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, pull a fleet report for Chrome versions below 149.0.7827.53, validate that auto-update plus relaunch enforcement is actually clearing stale builds, and patch your highest-value user groups first; for this MEDIUM finding there is noisgate mitigation SLAno mitigation SLA — go straight to the 365-day remediation window unless your threat model includes highly targeted browser data theft. Close the vulnerable version population under the noisgate remediation SLA within 365 days, but this does not warrant an emergency weekend change window on the evidence available as of 2026-06-05.

Sources

  1. NVD CVE-2026-10985
  2. Chrome stable desktop advisory URL referenced by NVD
  3. Chromium issue tracker reference
  4. CISA Known Exploited Vulnerabilities catalog
  5. FIRST EPSS data and statistics
  6. FIRST EPSS API documentation
  7. GovCERT.HK alert for Chrome 149.0.7827.53 update
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.