
Prueba de concepto y fuzzer GLSL para CVE-2026-9999 en el backend ANGLE/Metal WebGL de Chrome, con fingerprinting de compilación, shaders seleccionados y captura de artefactos de fallo.
| Campo | Valor |
|---|---|
| CVE | CVE-2026-9999 |
| Proveedor / producto | Google Chrome |
| Afectado | Chrome < 148.0.7778.216, solo macOS [1] |
| Corregido en | 148.0.7778.216 [1] |
| Impacto | Ejecución arbitraria de código dentro de un sandbox mediante una página HTML manipulada [1] |
| Severidad en Chromium | Alta [1] |
| CVSS 3.1 (CISA-ADP) | 8.8 ALTA — CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H [1] |
| Evaluación CVSS de NVD (NIST) | Aún no proporcionada [1] |
| CWE | CWE-269 — Gestión inadecuada de privilegios (enriquecimiento de CISA-ADP) [1] |
| CISA SSVC (2026-05-29) | exploitation: none, automatable: no, technicalImpact: total [1] |
| Publicado / última modificación | 2026-05-28 / 2026-07-21 [1] |
| Causa raíz | No pública — la incidencia 513364480 de Chromium muestra "Se requieren permisos" [1] |
Implicación en la cadena de ataque: la ejecución de código "dentro de un sandbox" [1] significa que un atacante obtiene el control de un proceso en sandbox (muy probablemente el proceso de GPU). Una toma completa del navegador requeriría además un escape de sandbox independiente que no forma parte de este CVE.
Lo siguiente es una inferencia del registro público, no hechos confirmados:
Por lo tanto, el harness ejercita exactamente esos patrones y luego muta GLSL a gran escala para buscar un fallo en el lado del renderizador (pérdida de contexto WebGL = fallo del proceso de GPU o muerte por watchdog).
| Archivo | Propósito |
|---|---|
cve-2026-9999-poc.html | Harness de PoC autocontenido (sin dependencias): fingerprinting de build, 8 shaders seleccionados de estrés del traductor, fuzzer de GLSL con captura de artefactos de fallo |
README.md | Este archivo |
El archivo Chrome for Testing de Google ofrece builds fijadas a una versión que no se autoactualizan. Encuentra el build vulnerable más reciente (todo lo anterior a 148.0.7778.216 está afectado [1]):
import json, urllib.request
data = json.load(urllib.request.urlopen(
"https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"))
key = lambda v: tuple(int(x) for x in v.split('.'))
fix = (148, 0, 7778, 216)
cands = sorted((v["version"] for v in data["versions"]
if "chrome" in v.get("downloads", {}) and key(v["version"]) < fix), key=key)
print(cands[-5:]) # pick the last (newest vulnerable) entry
Descarga para tu arquitectura (uname -m):
# Apple Silicon
https://storage.googleapis.com/chrome-for-testing-public/<VERSION>/mac-arm64/chrome-mac-arm64.zip
# Intel
https://storage.googleapis.com/chrome-for-testing-public/<VERSION>/mac-x64/chrome-mac-x64.zip
Descomprime en una carpeta de laboratorio (p. ej. ~/lab/, no /Applications) y ejecútalo desde ahí.
Si un build específico no está en Chrome for Testing, usa el archivo de snapshots de Chromium (commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/ para Intel, .../Mac_Arm/ para Apple Silicon), indexado por posición de commit — mapea la versión vulnerable a una posición de rama mediante chromium-history, y luego obtén el snapshot más cercano. Los snapshots tampoco se autoactualizan.
Termina los agentes de actualización de Keystone y bloquea googleupdate.googleapis.com, o el build de prueba se parcheará silenciosamente durante la noche. No es necesario para builds de Chrome for Testing.
Sin Metal, Chrome renderiza WebGL por software (SwiftShader) y el backend ANGLE Metal nunca se toca. En la consola de la página del PoC, ejecuta:
const c = document.createElement('canvas'), g = c.getContext('webgl2');
const x = g.getExtension('WEBGL_debug_renderer_info');
console.log(g.getParameter(x.UNMASKED_RENDERER_WEBGL));
// Good: contains "ANGLE Metal Renderer"
// Bad: contains "SwiftShader" -> the vulnerable path is NOT being exercised
También puedes confirmarlo en chrome://gpu. Los invitados de Parallels/VMware Fusion con virtualización de GPU suelen funcionar; las configuraciones mínimas de QEMU/UTM a menudo recurren a SwiftShader.
cd <repo dir>
python3 -m http.server 8000
# then browse to http://localhost:8000/cve-2026-9999-poc.html
1) Run curated triggers. Ocho shaders ejercitan los patrones del traductor descritos en §2 (indexación constante fuera de límites, dimensionado de arrays con desbordamiento de enteros, indexación dinámica de matrices, estrés de desenrollado de bucles, arrays de arrays, discard/swizzle, casos límite del preprocesador, UBOs sobredimensionados). Observa los resultados [!!] y los eventos de pérdida de contexto.2) Fuzz. Los shaders GLSL mutados se compilan, enlazan, dibujan y se leen de vuelta en un bucle. Observa el registro en busca de CONTEXT LOST.localStorage. Recupéralo:
localStorage.getItem("cve20269999_poc_fs"); // crashing fragment shader
localStorage.getItem("cve20269999_crashes"); // crash event log
Una instantánea en vivo de una ejecución sospechosa también es visible en
chrome://gpuy en la Consola de macOS (informes de fallo del proceso de GPU).
WEBGL_context_lost ≠ vulnerabilidad. El watchdog de GPU de Chrome mata shaders de larga duración (el disparador loop-unroll-dos y las iteraciones de fuzzing con recuentos de bucle enormes están diseñados para ser lentos). Elimina el ruido: reduce SH_ITER, o confirma que cualquier fallo candidato se reproduce rápidamente (< 1 s por iteración).EXC_BAD_ACCESS) en lugar de una terminación por watchdog.Compila una revisión vulnerable de Chromium con AddressSanitizer:
fetch chromium
cd src
git checkout tags/148.0.7778.215 # last tag before the fix
gn gen out/asan --args='is_asan=true is_debug=false symbol_level=1 dcheck_always_on=true'
autoninja -C out/asan chrome
Luego ejecuta el shader minimizado que falla con la validación de la API de Metal activada:
MTL_DEBUG_LAYER=1 out/asan/Chromium.app/Contents/MacOS/Chromium poc.html
El rastreo de ASAN nombrará la función exacta de ANGLE/Metal y confirmará si el fallo coincide con el componente del CVE [1].
(Posteriormente: una vez que el commit de corrección para 148.0.7778.216 sea visible, haz diff de third_party/angle/src/libANGLE/renderer/metal/ para identificar la causa raíz real y sustituye el enfoque de fuzzing por un disparador determinista.)
exploitation: none [1].Prueba solo en máquinas que sean tuyas o para las que tengas autorización explícita. El harness compila deliberadamente shaders adversariales para hacer fallar un proceso gráfico — espera muertes de procesos de GPU. Mantén el build vulnerable del navegador fuera de redes de producción.
[1] NVD — CVE-2026-9999: https://nvd.nist.gov/vuln/detail/CVE-2026-9999 * Aviso del proveedor (blog Chrome Releases, actualización del canal Stable): https://chromereleases.googleblog.com/2026/05/stable-channel-update-for-desktop_0877304591.html * Incidencia 513364480 de Chromium (acceso restringido): https://issues.chromium.org/issues/513364480