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

Use after free in WebRTC in Google Chrome prior to 149

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

This is a burglar getting into the lobby, not the vault

CVE-2026-10939 is a use-after-free in Chrome's WebRTC stack that affects Google Chrome builds before 149.0.7827.53. Google shipped the fix in the Chrome 149 stable release on June 2, 2026, with fixed builds listed as 149.0.7827.53 for Linux and 149.0.7827.53/54 for Windows and macOS. The bug is reachable from a malicious web page, so the trigger surface is broad: get a user onto attacker-controlled content and let the browser do the rest.

Google's HIGH / 8.8 label is technically fair for the memory-corruption primitive, but it overstates the likely enterprise outcome if you read it as 'one-click endpoint compromise.' The decisive reality check is that the stated impact is arbitrary code execution inside Chrome's sandbox; that means meaningful host compromise usually needs a second bug or some separate escape path. This stays important because Chrome is everywhere and the bug is remote, but it is not the same as a clean unauthenticated server-side RCE.

"Drive-by reachable, but this is renderer-sandbox code exec, not a one-bug workstation takeover."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Land the user on attacker content

The attacker needs the victim to render a malicious page that exercises WebRTC code paths, typically via JavaScript plus normal browser media/session setup. No account, extension, or local foothold is required; the browser is the target surface.
Conditions required:
  • Victim is running Google Chrome earlier than 149.0.7827.53
  • Victim loads attacker-controlled HTML/JavaScript
  • WebRTC is enabled and reachable in the target's browser policy
Where this breaks in practice:
  • This is UI:R: the victim still has to browse to, click, or otherwise render hostile content
  • Web filtering, browser isolation, and strong phishing resistance cut the reachable population
  • Not every enterprise workflow meaningfully uses arbitrary external WebRTC-heavy content
Detection/coverage: Perimeter vulnerability scanners will not see this. Coverage comes from browser version inventory, web proxy telemetry, and user-journey monitoring, not internet scanning.
STEP 02

Trigger the WebRTC lifetime bug

Once the page is open, the exploit uses WebRTC objects in a sequence that causes a freed object to be reused. In practice this is a reliability problem, not just a trigger problem: the attacker needs a stable primitive on the victim's platform and build.
Conditions required:
  • A weaponized exploit chain built on the WebRTC UAF
  • Platform-specific exploit reliability for the target OS/architecture
Where this breaks in practice:
  • Modern Chrome memory-safety hardening and allocator behavior raise exploit-development cost
  • Crashy proof-of-concept behavior is much easier than reliable post-corruption code execution
  • Cross-version exploit portability is poor once the fleet starts auto-updating
Detection/coverage: Likely signals are renderer crashes, browser exploit mitigation events, or anomalous child-process behavior. Signature-based network detection is weak.
STEP 03

Gain code execution in the renderer sandbox

If the memory corruption is made reliable, the attacker gets code execution in the compromised Chrome renderer process. That is serious, but the renderer is deliberately restricted and is not equivalent to native execution as the user outside Chrome's policy cage.
Conditions required:
  • Successful control over instruction flow or equivalent memory corruption primitive
  • Execution occurs in a sandboxed Chrome process
Where this breaks in practice:
  • The sandbox sharply limits filesystem writes, arbitrary OS access, and direct persistence
  • Site isolation and process isolation reduce what one renderer can directly reach
  • A single-bug result here is often limited to the browser security boundary, not the endpoint
Detection/coverage: EDR may catch abnormal renderer child-process spawning, exploit-guard hits, or blocked OS access attempts. Browser forensic visibility is uneven across enterprises.
STEP 04

Chain a sandbox escape for real endpoint impact

To turn this into a workstation compromise, the attacker typically needs a second vulnerability or a separate trust-boundary failure to escape the renderer sandbox. That missing second stage is the main reason this scores below a top-tier emergency for enterprise patch triage.
Conditions required:
  • A working sandbox escape, broker abuse, or separate local privilege path
  • Opportunity to execute a follow-on stage after renderer compromise
Where this breaks in practice:
  • No public evidence in the reviewed sources of an in-the-wild chain for this CVE
  • No KEV listing and very low EPSS reduce confidence that adversaries are prioritizing it now
  • Modern EDR, OS exploit protections, and application control are more likely to catch the noisier second stage
Detection/coverage: Second-stage behavior is where defenders are most likely to win: process injection, abnormal file writes, credential access, and persistence attempts are all better covered than the initial browser exploit.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public exploitation evidence located in the reviewed sources. Google did not note active exploitation in its June 2, 2026 stable release post.
Proof-of-concept availabilityNo public weaponized PoC located in the reviewed sources. The Chromium issue exists, but details appear access-restricted, which is normal while Chrome holds back bug specifics until most users are patched.
EPSS0.00071 from supplied intel; that is a very low exploit-likelihood signal relative to commonly abused internet-facing flaws.
KEV statusNot listed in CISA KEV at review time.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — remote and low-complexity, but user interaction is required and the CVSS line does not capture the practical importance of Chrome's sandbox boundary.
Affected versionsGoogle Chrome prior to 149.0.7827.53. Google published fixed stable builds as 149.0.7827.53 for Linux and 149.0.7827.53/54 for Windows/macOS on 2026-06-02.
Fixed versionsUpgrade to 149.0.7827.53+ on Linux and 149.0.7827.53/54+ on Windows/macOS. For enterprise packaging, trust the vendor/browser channel version rather than distro Chromium backport numbering.
Exposure and scanning realityThis is not meaningfully internet-enumerable with Shodan/Censys-style scanning because the target is a client browser, not a listening service. Your real exposed population is simply every endpoint still running vulnerable Chrome.
TimelineReported by Google on 2026-04-17 in the Chrome stable release notes; fix shipped in stable on 2026-06-02; user-supplied public disclosure date is 2026-06-04.
Researcher / reporting orgThe release note attributes this CVE to Google, not an external bounty reporter.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.4/10)

The single biggest downward pressure is that the advertised impact is code execution inside the Chrome renderer sandbox, which usually does not equal full host compromise by itself. It stays in HIGH because Chrome is ubiquitous, the bug is remote and low-complexity once a user renders malicious content, and a big enterprise will have plenty of reachable browsers even without public exploitation evidence.

HIGH Affected version range and fixed builds
MEDIUM Assessment that sandbox containment materially lowers real-world impact
MEDIUM Absence of public exploit / KEV / public PoC at review time

Why this verdict

  • Start at vendor 8.8: remote, no-privilege browser memory corruption on a massively deployed client is a legitimately dangerous baseline.
  • Subtract for UI:R and lure dependence: the attacker still needs the victim to render hostile content, which narrows reach compared with zero-click or server-side bugs.
  • Subtract for sandbox containment: the documented impact is renderer-sandbox code execution, so most meaningful endpoint outcomes require a second vulnerability or trust-boundary failure.
  • Subtract for weak threat signal: supplied EPSS 0.00071, no KEV listing, and no public in-the-wild note from Google all argue against emergency-grade prioritization.
  • Add back for exposure scale: unlike a niche app, Chrome is everywhere; even a partially constrained bug has broad fleet reach across a 10,000-host estate.

Why not higher?

This is not a clean one-bug workstation takeover in the way admins often hear 'RCE' and mentally model it. The need for user interaction plus the fact that execution lands inside the sandbox are two real, compounding brakes on enterprise blast radius.

Why not lower?

It is still a remote browser memory-corruption bug in one of the most deployed applications in the enterprise. No authentication is needed, complexity is low once the victim loads content, and the reachable population is far larger than for most authenticated or internal-only vulnerabilities.

05 · Compensating Control

What to do — in priority order.

  1. Force Chrome relaunch compliance — Use enterprise browser management, endpoint management, or logon scripts to make sure the fixed build is actually running, not merely downloaded. For a HIGH verdict, deploy this compensating measure within 30 days; Chrome auto-update without relaunch enforcement leaves stale vulnerable renderer processes on a large fleet.
  2. Prefer browser isolation for high-risk browsing — Route unmanaged internet browsing, contractor access, and high-risk user groups through remote/browser isolation where available. This reduces the value of a renderer compromise while you drive the fleet to the fixed build; for a HIGH verdict, put this in place or tighten policy within 30 days for the riskiest cohorts.
  3. Constrain WebRTC where business allows — If your environment does not rely heavily on browser-based voice/video apps, reduce or disable WebRTC exposure using enterprise Chrome policy for selected populations. That is a practical blast-radius reducer for this specific component and should be applied within 30 days where operationally safe.
  4. Harden second-stage containment — Make sure EDR exploit protection, application control, child-process restrictions, and browser-to-OS detection rules are tuned, because the attacker needs a follow-on stage to convert this into a host compromise. For a HIGH verdict, validate those controls within 30 days on standard workstation images.
What doesn't work
  • A network perimeter scanner will not meaningfully find this exposure because vulnerable Chrome is a client application, not a server listening on the internet.
  • Relying on auto-update alone is not enough if users do not relaunch; the vulnerable code stays live in existing browser processes.
  • MFA is largely irrelevant to the vulnerability itself; it may help downstream account abuse, but it does not stop the browser memory corruption.
  • Generic web proxy blocklists help only if they stop the lure entirely; once a user reaches allowed attacker-controlled content, they do not neutralize the WebRTC bug.
06 · Verification

Crowdsourced verification payload.

Run this on the target endpoint or through your EDR/remote execution platform. Invoke it with python3 check_chrome_cve_2026_10939.py on Linux/macOS or py check_chrome_cve_2026_10939.py on Windows; no admin privileges are required as long as the Chrome binary is readable in standard install paths.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# Check Google Chrome version for CVE-2026-10939
# Outputs: VULNERABLE / PATCHED / UNKNOWN
# 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 version_str(v):
    return '.'.join(str(x) for x in v)


def run_version(cmd):
    try:
        p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=10)
        out = (p.stdout or '') + ' ' + (p.stderr or '')
        return parse_version(out)
    except Exception:
        return None


def windows_candidates():
    paths = []
    env_roots = [
        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 root in env_roots:
        if not root:
            continue
        for suffix in suffixes:
            p = os.path.join(root, *suffix.split('\\'))
            if os.path.exists(p):
                paths.append(p)
    return paths


def mac_candidates():
    return [
        '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
        os.path.expanduser('~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')
    ]


def linux_candidates():
    cmds = []
    for name in ['google-chrome', 'google-chrome-stable', 'chrome']:
        p = shutil.which(name)
        if p:
            cmds.append(p)
    for p in ['/opt/google/chrome/chrome', '/usr/bin/google-chrome', '/usr/bin/google-chrome-stable']:
        if os.path.exists(p) and p not in cmds:
            cmds.append(p)
    return cmds


def collect_versions():
    system = platform.system().lower()
    found = []

    if 'windows' in system:
        for path in windows_candidates():
            v = run_version([path, '--version'])
            if v:
                found.append((path, v))
    elif 'darwin' in system:
        for path in mac_candidates():
            if os.path.exists(path):
                v = run_version([path, '--version'])
                if v:
                    found.append((path, v))
    else:
        for path in linux_candidates():
            v = run_version([path, '--version'])
            if v:
                found.append((path, v))

    return found


def main():
    found = collect_versions()
    if not found:
        print('UNKNOWN: Google Chrome not found in standard locations or version unreadable')
        sys.exit(2)

    vulnerable = []
    patched = []
    for path, ver in found:
        if ver < FIXED:
            vulnerable.append((path, ver))
        else:
            patched.append((path, ver))

    if vulnerable:
        details = '; '.join(f'{path}={version_str(ver)}' for path, ver in vulnerable)
        print(f'VULNERABLE: fixed version is {version_str(FIXED)}; found {details}')
        sys.exit(1)

    details = '; '.join(f'{path}={version_str(ver)}' for path, ver in patched)
    print(f'PATCHED: fixed version is {version_str(FIXED)}; found {details}')
    sys.exit(0)


if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat this as a high-priority browser fleet hygiene issue, not a panic-tier host-takeover emergency. Use relaunch enforcement, browser isolation for risky cohorts, and optional WebRTC restrictions where business-safe within 30 days under the noisgate mitigation SLA, then drive every managed endpoint to Chrome 149.0.7827.53/54 or later within 180 days under the noisgate remediation SLA; in practice, most enterprises should finish far sooner because browser version drift is easy to close once restart compliance is enforced.

Sources

  1. Google Chrome stable desktop release 149
  2. Google Chrome early stable desktop release 149.0.7827.53/54
  3. Google Chrome beta desktop update 149.0.7827.53
  4. Chromium sandbox design documentation
  5. Chromium sandbox FAQ
  6. CISA Known Exploited Vulnerabilities catalog
  7. FIRST EPSS overview
  8. Chromium issue tracker entry 503502607
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.