
Prova de conceito e fuzzer GLSL para o CVE-2026-9999 no backend WebGL ANGLE/Metal do Chrome, com fingerprinting de build, shaders selecionados e captura de artefatos de crash.
| Campo | Valor |
|---|---|
| CVE | CVE-2026-9999 |
| Fornecedor / produto | Google Chrome |
| Afetado | Chrome < 148.0.7778.216, somente macOS [1] |
| Corrigido em | 148.0.7778.216 [1] |
| Impacto | Execução arbitrária de código dentro de um sandbox por meio de uma página HTML especialmente criada [1] |
| Severidade Chromium | Alta [1] |
| CVSS 3.1 (CISA-ADP) | 8.8 HIGH — CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H [1] |
| Avaliação CVSS NVD (NIST) | Ainda não fornecida [1] |
| CWE | CWE-269 — Gerenciamento inadequado de privilégios (enriquecimento pela CISA-ADP) [1] |
| CISA SSVC (2026-05-29) | exploitation: none, automatable: no, technicalImpact: total [1] |
| Publicado / última modificação | 2026-05-28 / 2026-07-21 [1] |
| Causa raiz | Não pública — a issue 513364480 do Chromium mostra "Permissions Required" [1] |
Implicação para a cadeia de ataque: a execução de código "dentro de um sandbox" [1] significa que um atacante obtém o controle de um processo em sandbox (provavelmente o processo de GPU). Uma tomada completa do navegador exigiria adicionalmente uma fuga de sandbox separada que não faz parte deste CVE.
O seguinte é uma inferência a partir do registro público, não fatos confirmados:
Portanto, o harness exercita exatamente esses padrões e então muta GLSL em escala para caçar um crash no lado do renderizador (WebGL context lost = crash do processo de GPU ou kill pelo watchdog).
| Arquivo | Finalidade |
|---|---|
cve-2026-9999-poc.html | Harness PoC autocontido (sem dependências): fingerprinting de build, 8 shaders selecionados de estresse do tradutor, fuzzer GLSL com captura de artefatos de crash |
README.md | Este arquivo |
O arquivo Chrome for Testing do Google fornece builds fixados em versões específicas que não são atualizados automaticamente. Encontre o build vulnerável mais recente (tudo abaixo de 148.0.7778.216 é afetado [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
Baixe para a sua arquitetura (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
Descompacte em uma pasta de laboratório (ex.: ~/lab/, não /Applications) e execute a partir dela.
Se um build específico não estiver disponível no Chrome for Testing, use o arquivo de snapshots do Chromium (commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/ para Intel, .../Mac_Arm/ para Apple Silicon), indexado por posição de commit — mapeie a versão vulnerável para uma posição de branch via chromium-history e baixe o snapshot mais próximo. Snapshots também não são atualizados automaticamente.
Encerre os agentes de atualização do Keystone e bloqueie googleupdate.googleapis.com; caso contrário, o build de teste se atualizará silenciosamente durante a noite. Não é necessário para builds do Chrome for Testing.
Sem Metal, o Chrome renderiza WebGL por software (SwiftShader) e o backend ANGLE Metal nunca é acionado. No console da página do PoC, execute:
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
Você também pode confirmar em chrome://gpu. Convidados de Parallels/VMware Fusion com virtualização de GPU geralmente funcionam; configurações mínimas de QEMU/UTM frequentemente recorrem ao SwiftShader.
cd <repo dir>
python3 -m http.server 8000
# then browse to http://localhost:8000/cve-2026-9999-poc.html
1) Run curated triggers. Oito shaders exercitam os padrões do tradutor descritos na §2 (indexação constante fora dos limites, dimensionamento de arrays com estouro de inteiro, indexação dinâmica de matrizes, estresse de desenrolamento de loop, arrays de arrays, discard/swizzle, casos extremos de pré-processador, UBOs superdimensionados). Fique atento a resultados [!!] e eventos de perda de contexto.2) Fuzz. Shaders GLSL mutados são compilados, vinculados, renderizados e lidos de volta em um loop. Observe o log em busca de CONTEXT LOST.localStorage. Recupere-o:
localStorage.getItem("cve20269999_poc_fs"); // crashing fragment shader
localStorage.getItem("cve20269999_crashes"); // crash event log