This is a lockpick for a door you already had to break open first
CVE-2026-10961 is a use-after-free in Chrome for iOS affecting versions before 149.0.7827.53. Per the CVE description and Google's release notes, the attacker does not start from zero here; they must first compromise the renderer process and then use this bug to potentially perform a sandbox escape via a crafted HTML page.
Google's HIGH 8.3 is technically defensible in a lab, but it overstates Monday-morning enterprise urgency. In the real world this is a second-stage exploit primitive, not an initial-access bug: it requires user interaction, high attack complexity, and a separate renderer compromise before this CVE matters. On iOS, Chrome also operates within Apple's platform constraints, which further narrows practical blast radius versus desktop Chrome RCE headlines.
4 steps from start to impact.
Land the victim on attacker HTML
- Victim uses Chrome for iOS < 149.0.7827.53
- Victim browses to attacker-controlled content
- Attacker has or develops a separate renderer-compromise bug
- User interaction is required
- No public one-click exploit chain was found
- Mobile phishing conversion rates and managed-link protections reduce reach
Compromise the renderer with a separate bug
- A viable renderer exploit exists
- The target page reaches the vulnerable rendering path
- Mitigations in the iOS browser stack are bypassed
- This is a prior-compromise prerequisite
- Exploit development cost is high
- No public PoC or in-the-wild reporting was found for this CVE
Use CVE-2026-10961 for sandbox escape
- Renderer already compromised
- Target remains on vulnerable Chrome for iOS build
- The exploit reliably hits the vulnerable object lifetime state
- Memory-corruption reliability on modern mobile targets is hard
- Restricted bug details suggest Google limited disclosure pending patch uptake
- Successful escape still may not equal full-device compromise
Harvest browser-app access, then chain again for device-level impact
- Successful browser-level escape
- Valuable enterprise sessions or tokens present in Chrome
- Attacker has a follow-on objective beyond the browser
- Chrome on iOS is still subject to Apple's app sandbox model
- Enterprise browser tokens may already be isolated or short-lived
- Many fleets have low Chrome-for-iOS population compared with desktop Chrome
The supporting signals.
| In-the-wild status | No confirmed active exploitation found in the sources reviewed. Not listed in CISA KEV. |
|---|---|
| Proof-of-concept availability | No public PoC found for CVE-2026-10961. The Chromium issue exists but is access-restricted, which is normal for memory-corruption bugs before broad patch uptake. |
| EPSS | 0.00068 (user-supplied) — extremely low predicted exploitation probability. |
| KEV status | Not KEV-listed as of the reviewed CISA catalog. |
| CVSS vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H — the key modifiers are high complexity and user interaction required. |
| Affected versions | Google Chrome on iOS prior to 149.0.7827.53. |
| Fixed version | 149.0.7827.53 or later for Chrome on iOS. |
| Disclosure timeline | Google's June 2026 release notes list CVE-2026-10961 and note it was reported by Google on 2026-04-30; user-supplied public disclosure date is 2026-06-04. |
| Researcher / reporter | Google is credited as the reporter in the Chrome release notes. |
| Scanning / exposure reality | Shodan/Censys/FOFA are basically irrelevant here. This is a client-side mobile browser issue, not an internet-listening service, so exposure has to be measured from MDM/app inventory, not perimeter scan counts. |
noisgate verdict.
The decisive factor is that this bug requires a prior renderer compromise, which makes it a second-stage exploit primitive rather than an initial access path. That prerequisite sharply reduces the reachable population and pushes this out of the same operational bucket as single-bug browser RCEs or KEV-listed web-facing flaws.
Why this verdict
- Major downward adjustment: requires prior renderer compromise — the vendor 8.3 starts from a network-reachable attacker, but real exploitation starts only after another bug has already succeeded.
- Second downward adjustment: limited exposed population — this is Chrome on iOS, not a server or a web-facing appliance. Only the subset of your fleet that runs vulnerable Chrome for iOS is in scope, and many enterprises have modest iOS Chrome adoption.
- Third downward adjustment: no current exploitation signals — no KEV entry, no public PoC found, and the supplied EPSS 0.00068 is extremely low.
- Why it stays MEDIUM instead of LOW — once the attacker has renderer code execution, a sandbox-escape primitive is still strategically valuable because it can widen access to browser-held enterprise sessions and managed web data.
Why not higher?
This is not a one-bug remote compromise story. The attacker must first win a separate renderer exploit, then reliably trigger this memory bug under mobile constraints, and there is no public evidence that defenders are seeing this chained in the wild.
Why not lower?
Even with the friction, browser sandbox escapes are not harmless cleanup bugs. If you have high-risk users on iOS Chrome, a working chain could still expose authenticated enterprise web sessions and defeat assumptions about renderer isolation.
What to do — in priority order.
- Enforce a minimum Chrome iOS version in MDM — Set a compliance rule that flags or blocks Chrome for iOS versions below 149.0.7827.53. For a MEDIUM noisgate verdict there is no mitigation SLA; use normal mobile governance and complete the actual patch inside the 365-day remediation window.
- Scope where Chrome on iOS is allowed — If your managed-browser strategy allows it, limit Chrome on iOS use for executives, admins, and other high-value targets until version compliance is clean. There is no mitigation SLA for MEDIUM, so do this as part of normal risk reduction rather than emergency change control.
- Harden web session exposure — Reduce the value of a browser-level escape by enforcing short-lived SSO tokens, managed account separation, and conditional access for sensitive apps. For MEDIUM issues, fold this into routine hardening while still ensuring vulnerable app versions are removed within the 365-day remediation window.
- Use MTD telemetry for suspicious browser abuse — Where you have mobile threat defense, alert on suspicious browsing flows, repeated browser crashes, and device noncompliance tied to outdated Chrome versions. This will not prevent exploitation by itself, but it helps surface outlier devices while patching proceeds on the standard MEDIUM track.
- Perimeter vulnerability scanning doesn't help; this is a client-side iOS app issue, not a network service.
- WAF rules won't reliably stop a renderer-compromise-plus-sandbox-escape chain delivered through normal web content.
- Relying on Apple platform security alone is not enough; the whole point of this CVE is to weaken browser-process isolation after a renderer compromise.
Crowdsourced verification payload.
Run this on an auditor workstation against a CSV export from your MDM/UEM that includes at least app name and version columns. Invoke it as python3 check_chrome_ios_cve_2026_10961.py devices_apps.csv; no admin rights are needed, but you need read access to the inventory export.
#!/usr/bin/env python3
# check_chrome_ios_cve_2026_10961.py
# Exit codes:
# 0 = PATCHED (no vulnerable Chrome for iOS entries found)
# 1 = VULNERABLE (one or more vulnerable entries found)
# 2 = UNKNOWN (could not determine from input)
import csv
import re
import sys
from typing import Optional
FIXED_VERSION = "149.0.7827.53"
APP_PATTERNS = [
re.compile(r"^google chrome$", re.I),
re.compile(r"^chrome$", re.I),
re.compile(r"^google chrome for ios$", re.I),
]
def normalize_version(v: str):
parts = re.findall(r"\d+", v or "")
if not parts:
return None
return tuple(int(x) for x in parts)
def cmp_versions(a: str, b: str) -> Optional[int]:
va = normalize_version(a)
vb = normalize_version(b)
if va is None or vb is None:
return None
max_len = max(len(va), len(vb))
va = va + (0,) * (max_len - len(va))
vb = vb + (0,) * (max_len - len(vb))
if va < vb:
return -1
if va > vb:
return 1
return 0
def is_chrome_ios(app_name: str) -> bool:
if not app_name:
return False
return any(p.match(app_name.strip()) for p in APP_PATTERNS)
def pick(row: dict, *candidates):
lowered = {k.strip().lower(): v for k, v in row.items() if k is not None}
for c in candidates:
if c.lower() in lowered:
return lowered[c.lower()]
return ""
def main():
if len(sys.argv) != 2:
print("UNKNOWN - usage: python3 check_chrome_ios_cve_2026_10961.py <mdm_export.csv>")
sys.exit(2)
path = sys.argv[1]
found_any = False
found_chrome = False
vulnerable = []
unknown = []
try:
with open(path, newline='', encoding='utf-8-sig') as f:
reader = csv.DictReader(f)
if not reader.fieldnames:
print("UNKNOWN - CSV has no header row")
sys.exit(2)
for row in reader:
found_any = True
device = pick(row, "DeviceName", "Device", "Name", "Hostname", "SerialNumber", "UDID") or "UNKNOWN_DEVICE"
app = pick(row, "AppName", "Application", "App", "ManagedAppName", "BundleDisplayName")
version = pick(row, "Version", "AppVersion", "ShortVersion", "CFBundleShortVersionString")
platform = pick(row, "Platform", "OS", "OperatingSystem")
# If the export mixes platforms, keep iOS/iPadOS rows preferred but don't hard-fail.
if app and is_chrome_ios(app):
found_chrome = True
c = cmp_versions(version, FIXED_VERSION)
if c is None:
unknown.append((device, version or "<missing>", platform or "<unknown>"))
elif c < 0:
vulnerable.append((device, version, platform or "<unknown>"))
except FileNotFoundError:
print(f"UNKNOWN - file not found: {path}")
sys.exit(2)
except Exception as e:
print(f"UNKNOWN - failed to parse CSV: {e}")
sys.exit(2)
if not found_any:
print("UNKNOWN - CSV contains no data rows")
sys.exit(2)
if vulnerable:
print(f"VULNERABLE - found {len(vulnerable)} device(s) with Chrome for iOS < {FIXED_VERSION}")
for device, version, platform in vulnerable[:25]:
print(f" {device} | version={version} | platform={platform}")
if len(vulnerable) > 25:
print(f" ... {len(vulnerable) - 25} more")
if unknown:
print(f"NOTE - {len(unknown)} Chrome row(s) had unreadable versions and need manual review")
sys.exit(1)
if found_chrome:
if unknown:
print(f"UNKNOWN - no confirmed vulnerable rows, but {len(unknown)} Chrome row(s) had unreadable versions")
for device, version, platform in unknown[:25]:
print(f" {device} | version={version} | platform={platform}")
sys.exit(2)
print(f"PATCHED - all discovered Chrome for iOS entries are >= {FIXED_VERSION}")
sys.exit(0)
print("UNKNOWN - no Chrome for iOS rows found in the CSV; verify your export includes app inventory")
sys.exit(2)
if __name__ == "__main__":
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.