← Back to Feed CACHED · 2026-06-05 16:54:33 · CACHE_KEY CVE-2026-10938
CVE-2026-10938 · CWE-20 · Disclosed 2026-06-04

Google Chrome Input insufficient input validation allowing post-renderer-compromise browser boundary bypass

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

This is a flaw in the bank vault’s inner cage, not the lobby door

CVE-2026-10938 affects Google Chrome prior to 149.0.7827.53 on Linux and prior to 149.0.7827.53/54 on Windows and macOS. The user-supplied title says *"Inappropriate implementation in Input"*, but Google’s June 2, 2026 stable-channel advisory lists it as *"Insufficient validation of untrusted input in Input"* and tags it High in Chromium’s internal severity language. The important part is the attack precondition: the attacker must already have compromised the renderer process before this bug matters.

In practice, that makes this a post-initial-compromise browser chain component, not a stand-alone drive-by. Vendor-style wording can make these look scarier than they usually are in enterprise triage because *site-isolation/sandbox-boundary* bugs sit behind another exploit stage. Still, this is not ignorable: if an attacker already has renderer code execution, a boundary-bypass in Chrome can turn a contained foothold into cross-origin data access or a stronger follow-on position. That keeps it above LOW, but the renderer-compromise prerequisite drags it down to = ASSESSED AT MEDIUM.

"Stage-two Chrome chain bug: real boundary bypass, but only after the attacker already owns the renderer."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land renderer compromise first

The attacker needs a separate stage-one Chrome bug to get code execution or equivalent control inside the renderer process. Think *malicious HTML/JS exploit* as the initial weaponized entry, with CVE-2026-10938 acting only as the follow-on stage.
Conditions required:
  • Victim browses attacker-controlled content
  • A separate renderer compromise primitive exists and works against the victim build
  • Chrome process mitigations do not stop the stage-one exploit
Where this breaks in practice:
  • This CVE does nothing by itself; another exploit must already succeed
  • Modern Chrome hardening and rapid auto-update reduce the usable population for the first-stage bug
  • Exploit chaining is materially harder than single-bug web compromise
Detection/coverage: Network scanners will not see this. Browser exploit telemetry, crash reporting, EDR child-process anomalies, and exploit-protection logs are your best weak signals, but coverage is inconsistent.
STEP 02

Trigger the Input bug as stage two

With renderer control established, the attacker feeds Chrome a crafted page state that exercises the vulnerable Input path. The goal is to abuse insufficient validation so the compromised renderer can cross a boundary it should not be able to cross.
Conditions required:
  • Renderer process already under attacker influence
  • Victim is on a vulnerable Chrome build before 149.0.7827.53/54
  • Attacker can deliver crafted HTML/content to the live session
Where this breaks in practice:
  • Official bug details are restricted, which slows commodity weaponization
  • No public PoC was identified in the reviewed sources
  • Per-build reliability is usually fragile for browser chain components
Detection/coverage: No broad scanner coverage. You mostly detect this indirectly through version inventory plus correlation with other Chrome exploitation attempts.
STEP 03

Bypass site isolation / browser boundary

If successful, the attacker weakens Chrome’s defense-in-depth boundary after renderer compromise. Practically, that can mean access beyond the compromised origin’s lane, depending on the exact exploit chain and victim browsing context.
Conditions required:
  • Vulnerable Input path reachable from the compromised renderer
  • Useful target data or cross-origin context exists in the browser session
Where this breaks in practice:
  • Blast radius is bounded by what the browser session actually has open and accessible
  • Some enterprise controls reduce value, such as separate profiles, ephemeral sessions, and forced sign-out patterns
  • This is still browser-internal abuse, not direct domain-controller magic
Detection/coverage: Hard to see directly. Browser forensic artifacts, abnormal tab/process behavior, and downstream session misuse are more likely to be observable than the bypass itself.
STEP 04

Monetize via session theft or follow-on access

The attacker uses the upgraded browser foothold to steal tokens, read cross-origin data, or support later actions as the user. The vulnerability’s value is therefore mostly as a chain amplifier for espionage, account takeover, or lateral phishing operations.
Conditions required:
  • High-value authenticated web sessions present in the browser
  • Attacker has infrastructure to exfiltrate or act on stolen session material
Where this breaks in practice:
  • MFA does not help much once live browser session artifacts are stolen, but short session lifetimes and reauth policies do
  • Not every compromised browser is carrying valuable authenticated sessions at the moment of exploitation
Detection/coverage: Watch for suspicious token reuse, impossible travel, unusual SaaS session creation, and browser-originated access anomalies rather than expecting a neat CVE-specific alert.
03 · Compensating Control

1
Force browser auto-update — Remove version pinning, stale rings, and broken updater states so Chrome can move to patched builds quickly. For a MEDIUM verdict there is no noisgate mitigation SLA; treat this as standard hygiene and complete patch rollout within the 365-day remediation window, though browser fleets should normally converge far sooner.
2
Keep site isolation and Chrome hardening defaults enabled — Do not relax Chrome security flags, enterprise policies, or sandbox-related settings to accommodate legacy apps. There is no mitigation SLA for MEDIUM, so do this in the next normal hardening cycle while still remediating with the vendor-fixed version inside 365 days.
3
Prioritize with any concurrent Chrome renderer-RCE findings — This CVE is most dangerous as part of a chain, so if your backlog also includes Chrome renderer execution bugs, treat the pair as higher operational risk than either ticket alone. There is no mitigation SLA for MEDIUM here, but chain-aware patch grouping should happen during your next browser maintenance wave, not as an isolated long-tail exception.
4
Hunt for outdated or unmanaged Chrome installs — Developer workstations, VDI gold images, kiosk systems, and non-standard packaging channels are where browser drift hides. Because this verdict is MEDIUM, there is no mitigation SLA — go straight to the 365-day remediation window, but unmanaged browsers should be cleaned up in routine asset hygiene much earlier.
What doesn't work
  • Perimeter scanning doesn't help; this is a client-side browser flaw, not an exposed server port.
  • WAF rules do not meaningfully mitigate a renderer-compromise chain inside the user’s browser session.
  • MFA alone is not a control here; if an attacker steals live browser session artifacts after compromise, MFA has already been bypassed at the session layer.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed active exploitation in reviewed sources. Not listed in CISA KEV, and Google’s release post does not note in-the-wild abuse.
Public exploit / PoCNo public PoC identified. The Chromium issue reference exists, but bug details are restricted, which is normal while fixes propagate.
EPSS0.00021 (~0.021%) from the user-supplied intel. That is very low modeled near-term exploitation probability; percentile was not confirmed in the reviewed sources.
KEV statusNot KEV-listed as of the reviewed CISA catalog page.
Vendor severity languageHigh in Chromium’s advisory taxonomy, but no vendor/authority CVSS score was published in the sources reviewed.
Affected versionsChrome Desktop before 149.0.7827.53 on Linux and before 149.0.7827.53/54 on Windows/macOS.
Fixed versionsPatched in 149.0.7827.53 (Linux) and 149.0.7827.53/54 (Windows/macOS). Android 149.0.7827.59 inherits the corresponding desktop security fixes. For distro-packaged Chromium, verify backports in distro changelogs instead of comparing only upstream version strings.
Reachability reality checkRequires attacker position = compromised renderer. That implies a prior successful browser exploit stage. This is major downward pressure on operational severity.
Scanning / exposure dataShodan/Censys/FOFA are mostly irrelevant here. Chrome is a client application, not an internet-facing service, so classic exposure counting does not meaningfully rank risk for this CVE.
Disclosure / reporting timelineGoogle’s stable-channel advisory was published June 2, 2026; Canada’s Cyber Centre echoed it June 3, 2026. Chrome’s release notes say CVE-2026-10938 was reported by Google on April 14, 2026.

Sources.

  1. Chrome Releases June 2026 archive
  2. Canadian Centre for Cyber Security advisory AV26-544
  3. CISA Known Exploited Vulnerabilities Catalog
  4. FIRST EPSS API lookup for CVE-2026-10938
  5. FIRST EPSS overview
  6. Chromium issue 502681591
  7. Singapore CSA bulletin, 03 Jun 2026
  8. Chrome Enterprise previous release notes
05 · The Call

Final Verdict
↓ DOWNGRADED to MEDIUM (5.0/10)

Why this verdict

  • Big downgrade for attacker position — exploitation requires a compromised renderer process, which implies the attacker has already landed a separate browser exploit stage. That sharply narrows real-world reach versus a normal unauthenticated web RCE.
  • Still a real security boundary issue — once chained, this can undermine site isolation / containment and expose higher-value browser session data. On a workforce fleet full of SSO sessions, that is materially useful to an operator.
  • Threat intel is cool, not hot — no KEV, no public PoC found, and EPSS is only 0.00021. That is weak evidence for broad near-term exploitation pressure.

Why not higher?

It is not higher because this is not a one-bug compromise path. Requiring prior renderer compromise means the attacker is already inside Chrome’s sandbox lane, so the reachable population is the subset of users who are also vulnerable to a separate stage-one exploit and are worth chaining against.

Why not lower?

It is not lower because site-isolation and browser-boundary bypasses are valuable once a browser foothold exists. In enterprises, a chained browser exploit can expose live SaaS sessions, tokens, and cross-origin data that materially increase attacker payoff even without host-level code execution.

06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or through your endpoint management agent, not from an auditor workstation. Invoke it with python3 chrome_cve_2026_10938_check.py on macOS/Linux or py chrome_cve_2026_10938_check.py on Windows; standard user rights are usually enough because it only reads local install metadata and runs --version.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# CVE-2026-10938 Chrome version check
# Outputs: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

import os
import platform
import re
import shutil
import subprocess
import sys
from pathlib import Path

PATCH_MIN = (149, 0, 7827, 53)
VERSION_RE = re.compile(r'(\d+)\.(\d+)\.(\d+)\.(\d+)')


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 run_version(cmd):
    try:
        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=10)
        out = (p.stdout or '') + '\n' + (p.stderr or '')
        return parse_version(out), out.strip()
    except Exception:
        return None, ''


def candidate_paths():
    system = platform.system().lower()
    paths = []

    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 not base:
                continue
            for suffix in suffixes:
                paths.append(str(Path(base) / suffix))

    elif system == 'darwin':
        paths.extend([
            '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
            '/Applications/Chromium.app/Contents/MacOS/Chromium',
            str(Path.home() / 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome'),
            str(Path.home() / 'Applications/Chromium.app/Contents/MacOS/Chromium'),
        ])

    else:
        for name in ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']:
            found = shutil.which(name)
            if found:
                paths.append(found)
        paths.extend([
            '/usr/bin/google-chrome',
            '/usr/bin/google-chrome-stable',
            '/usr/bin/chromium',
            '/usr/bin/chromium-browser',
            '/snap/bin/chromium',
            '/opt/google/chrome/chrome',
        ])

    # de-duplicate while preserving order
    seen = set()
    uniq = []
    for p in paths:
        if p and p not in seen:
            uniq.append(p)
            seen.add(p)
    return uniq


def compare_version(v):
    return v >= PATCH_MIN


def main():
    tested = []
    found_any = False

    for path in candidate_paths():
        if os.path.exists(path) or shutil.which(path):
            found_any = True
            version, raw = run_version([path, '--version'])
            tested.append((path, version, raw))
            if version is not None:
                if compare_version(version):
                    print(f'PATCHED - {path} - version {".".join(map(str, version))}')
                    sys.exit(0)
                else:
                    print(f'VULNERABLE - {path} - version {".".join(map(str, version))}')
                    sys.exit(1)

    if not found_any:
        print('UNKNOWN - Chrome/Chromium executable not found in common locations')
        sys.exit(2)

    # Found something but could not parse any version
    print('UNKNOWN - Found browser executable(s) but could not parse version')
    for path, version, raw in tested:
        msg = raw.replace('\n', ' ').strip()
        if len(msg) > 120:
            msg = msg[:117] + '...'
        print(f'INFO - {path} - raw output: {msg}')
    sys.exit(2)


if __name__ == '__main__':
    main()