
CVE-2026-5281 (Chrome Dawn WebGPU UAF) : analyse, outils de validation en laboratoire et environnement reproductible pour les builds vulnérables vs corrigés.
Cette vulnérabilité a affecté l'un des clients auxquels nous fournissons des services. Ce dépôt est notre contribution à la recherche originale : un point de départ centralisé pour le groupe, afin que si une vulnérabilité similaire affectant ce composant réapparaît, nous ayons déjà les bases en place. Il rassemble la théorie derrière le bug, un résumé documenté des conclusions du chercheur original, et un ensemble d'outils pratiques pour vérifier l'exposition dans un environnement de laboratoire.
Note : j'aurais aimé partager davantage de cette recherche, mais en raison de restrictions de l'entreprise, je ne peux pas la divulguer davantage. Tout ce qui est inclus ici a été examiné et ne viole aucun accord auquel je suis soumis. Le dépôt est donc archivé dans son état actuel.
Le 1er avril 2026, Google a publié une mise à jour de sécurité Chrome corrigeant 21 vulnérabilités, dont l'une, CVE-2026-5281, était déjà activement exploitée dans la nature au moment de la divulgation. Trois jours plus tard, la CISA l'a ajoutée au catalogue des vulnérabilités connues exploitées et a émis une directive opérationnelle contraignante exigeant des agences fédérales qu'elles appliquent le correctif. À ce moment-là, elle nous avait déjà affectés.
Ce dépôt existe pour une seule raison : que la prochaine fois que quelque chose comme cela se produit, nous ayons un point de départ au lieu de repartir de zéro. Il rassemble :
Lorsque vous voulez comprendre pourquoi une vulnérabilité existe, commencez par ce que le système a été conçu pour faire et les hypothèses sur lesquelles il est fondé.
WebGPU expose une API pour effectuer des opérations, telles que le rendu et le calcul, sur une unité de traitement graphique. WebGPU n'est pas une tentative d'exposer OpenGL ou OpenGL ES (Embedded Systems). C'est une nouvelle API construite sur les idées des APIs modernes telles que Direct3D 12, Metal et Vulkan.
WebGPU est le remplaçant moderne de WebGL, l'ancienne API GPU que les navigateurs utilisent depuis des années. La différence clé est que WebGPU a été conçu dès le départ pour la sécurité et la gestion explicite des ressources. Vous déclarez vous-même le cycle de vie de chaque tampon, texture et pipeline. Le navigateur agit comme une couche de validation entre votre JavaScript et le matériel GPU.
Les objets au centre de cette vulnérabilité, dans l'ordre de création :``` GPUAdapter ← represents a physical GPU or software fallback └─ GPUDevice ← your logical connection to the adapter; owns everything ├─ GPUBuffer ← a chunk of GPU-accessible memory ├─ GPUShaderModule ← a compiled WGSL shader program ├─ GPUComputePipeline ← a shader wired to a pipeline layout ├─ GPUBindGroup ← binds buffers as inputs to a pipeline ├─ GPUCommandEncoder ← records a sequence of GPU commands └─ GPUQueue ← submits recorded commands to hardware
La règle qui compte ici : chaque objet appartient au GPUDevice. Détruire un buffer alors que le GPUDevice a encore des commandes en cours d'exécution qui le référencent est explicitement illégal selon la spécification. L'implémentation Dawn est censée détecter et rejeter cela. CVE-2026-5281 est un cas où elle ne l'a pas fait.
---
---
---
<div id='whatisdawn'/>
## ***⚙️ Qu'est-ce que Dawn ?***
- **[Dawn - Implémentation WebGPU open-source](https://dawn.googlesource.com/dawn)**
> Dawn est une implémentation open-source et multiplateforme du standard WebGPU en cours de développement. Elle expose une API C++ native qui reflète l'IDL WebGPU avec quelques extensions.
Dawn est la bibliothèque C++ intégrée à Chrome qui traduit les appels JavaScript WebGPU en commandes GPU natives de la plateforme. Sous Windows, elle cible D3D12 ; sous macOS, elle cible Metal ; et sous Linux, elle cible Vulkan. Elle se situe entre le moteur JavaScript de Chrome et le pilote matériel, et elle est responsable de quatre choses : valider les appels API, sérialiser les commandes, suivre la durée de vie des objets et faire remonter les erreurs à JavaScript.
CVE-2026-5281 se situe dans la partie du suivi de durée de vie. Plus précisément, dans la durée pendant laquelle Dawn maintient en vie les objets buffer GPU alors que des commandes qui les référencent sont encore en attente d'exécution sur la file matérielle.```
JavaScript (V8)
│ WebGPU API calls
▼
Dawn (C++) - validates, serializes, tracks lifetimes, reports errors
│
▼
D3D12 (Windows) - Metal (macOS) - Vulkan (Linux)
│
▼
GPU hardware driver
│
▼
Physical GPU - shader cores, VRAM
Vous avez besoin d'un modèle mental clair de l'endroit où se trouvent les choses en mémoire avant qu'un Use-After-Free ne prenne tout son sens.``` High addresses ┌────────────────────────────────────┐ │ Kernel space │ The OS and drivers live here. │ │ User-mode code cannot touch it. ├────────────────────────────────────┤ │ Stack │ Function call frames. Fast. │ (grows downward) │ Freed automatically when the │ │ function returns. ├────────────────────────────────────┤ │ Heap │ Dynamic allocations - malloc, new, │ (grows upward) │ smart pointers like Ref. │ │ Freed only when you say so. ├────────────────────────────────────┤ │ BSS / Data / Text │ Globals, constants, compiled code. └────────────────────────────────────┘ Low addresses
Les objets C++ de Dawn, comme l'objet interne qui soutient un GPUBuffer, vivent sur le tas. Ils sont comptés par référence : un pointeur intelligent maintient un compteur du nombre de choses qui détiennent une référence sur l'objet. Lorsque ce compteur atteint zéro, le destructeur s'exécute et la mémoire est rendue à l'allocateur.
Un GPUBuffer a deux représentations en même temps, une côté CPU et une côté GPU :```
CPU side (Dawn, system RAM)
└─ C++ object - metadata, state flags, and a hardware handle
│
│ handle: ID3D12Resource* (D3D12) - MTLBuffer (Metal) - VkBuffer (Vulkan)
▼
GPU side (driver, VRAM)
└─ Actual memory allocation on the graphics card
Lorsque JavaScript appelle buffer.destroy(), le comportement prévu est : marquer l'objet comme détruit, décrémenter le compteur de références, libérer le handle matériel et libérer la VRAM. Le bug de CVE-2026-5281 provoque la libération de la VRAM alors que la file de commandes GPU détient toujours une référence à ce handle matériel, ce qui signifie que le GPU lit ou écrit activement dans de la mémoire qui ne lui appartient plus.
CWE-416 : Use After Free (MITRE)
Le fait de référencer de la mémoire après qu'elle a été libérée peut provoquer le crash d'un programme, l'utilisation de valeurs inattendues ou l'exécution de code. L'utilisation de mémoire précédemment libérée peut avoir de nombreuses conséquences néfastes, allant de la corruption de données valides à l'exécution de code arbitraire.
Une Use-After-Free suit un schéma fixe en trois étapes et constitue l'une des classes de bugs de sécurité mémoire les plus constamment exploitées dans la sécurité des navigateurs :```
Après l’étape 2, l’allocateur peut attribuer cette même région mémoire à une allocation complètement différente. Si un attaquant peut contrôler ce qui est placé dans cette région libérée, une technique appelée heap grooming, il peut contrôler ce que le pointeur obsolète relit. C’est ainsi qu’un bug de sécurité mémoire devient de l’exécution de code.
L’UAF côté GPU est plus difficile à observer que l’UAF côté CPU, car :
- L’« allocateur » est l’allocateur VRAM du pilote GPU, pas le malloc système.
- Le « pointeur obsolète » est un handle matériel toujours référencé par la file de commandes.
- Le GPU exécute les commandes de manière asynchrone, le CPU est passé à autre chose bien avant que le crash ne se produise.
---
---
---
<div id='thevulnerability'/>
## ***🕳️ La vulnérabilité***
---
<div id='thevulnerability-whatweknow'/>
### ***📋 Ce que nous savons grâce aux sources publiques***
Ce qui suit repose entièrement sur ce qui a été confirmé publiquement.
- **[NVD: CVE-2026-5281](https://nvd.nist.gov/vuln/detail/CVE-2026-5281)**
> Une use-after-free dans Dawn, dans les versions de Google Chrome antérieures à 146.0.7680.178, a permis à un attaquant distant ayant compromis le processus de rendu d’exécuter du code arbitraire via une page HTML conçue à cet effet.
- **[The Hacker News: 1er avril 2026](https://thehackernews.com/2026/04/new-chrome-zero-day-cve-2026-5281-under.html)**
> Google sait qu’un exploit pour CVE-2026-5281 existe dans la nature.
- **[Help Net Security: 1er avril 2026](https://www.helpnetsecurity.com/2026/04/01/google-chrome-zero-day-cve-2026-5281/)**
> La CVE-2026-5281 a été signalée par un chasseur de bugs sous pseudonyme (86ac1f1587b71893ed2ad792cd7dde32), qui avait déjà signalé deux vulnérabilités corrigées dans la mise à jour de Chrome publiée le 23 mars 2026 : un débordement de tampon du tas dans WebGL (CVE-2026-4675) et une autre vulnérabilité de type use-after-free dans Dawn (CVE-2026-4676). Le chasseur de bugs a également signalé une troisième vulnérabilité de type use-after-free dans Dawn (CVE-2026-5284), qui a été corrigée cette fois.
---
<div id='thevulnerability-executionlayers'/>
### ***🔗 De JavaScript au matériel***
Pour comprendre d’où une UAF dans Dawn peut provenir, il est utile de voir exactement comment un appel WebGPU passe d’une ligne de JavaScript jusqu’au matériel physique :```
JavaScript
↓ navigator.gpu → adapter → device → buffer / pipeline / encoder
↓ queue.submit([commandBuffer]) ← validation happens here
↓ buffer.destroy() ← if this races GPU execution, UAF
Dawn (C++) - validates API calls, serializes commands, tracks lifetimes
↓ translates WebGPU calls to platform-native API calls
D3D12 (Windows)
↓ ID3D12CommandQueue::ExecuteCommandLists()
↓ hardware handle for the buffer passed to the driver
GPU hardware
↓ shader cores execute the queued commands
↓ if the buffer was freed prematurely → they access freed VRAM ← UAF
La tension fondamentale est que queue.submit() et buffer.destroy() sont tous deux des appels d'API JavaScript qui retournent immédiatement, mais le GPU exécute les commandes soumises de manière asynchrone, potentiellement longtemps après que les deux appels ont retourné leur valeur. Dawn doit maintenir les objets buffer en vie pendant toute la durée de l'exécution GPU, et pas seulement jusqu'au retour de l'appel JavaScript.
Lorsque l'UAF se déclenche, le GPU rencontre ce que D3D12 appelle un événement "Device Removed". La séquence est:```
C'est également ce que détecte le runner de tests automatisés de ce dépôt : il surveille ces signaux de console exacts pour déterminer si la vulnérabilité est déclenchable dans une version donnée de Chrome.
---
<div id='thevulnerability-impact'/>
### ***💥 Impact et exigences d'exploitation***
La description de la NVD est précise sur une contrainte importante : l'exploitation exige que l'attaquant ait déjà compromis le processus de rendu. Cela signifie que CVE-2026-5281 n'est pas une RCE autonome en un clic à froid, mais une évasion de sandbox qui fait partie d'une chaîne.
En pratique, une chaîne d'attaque complète ressemblerait à ceci :```
Initial access ← some other vulnerability gets code running in the renderer
↓
CVE-2026-5281 ← UAF in Dawn used to escape the renderer sandbox
↓
Arbitrary code ← execution in a higher-privilege Chrome process or OS context
C'est exactement le modèle d'exploitation qui rend les bugs GPU des navigateurs si précieux : une fois que vous êtes dans le renderer, Dawn est l'une des prochaines cibles naturelles, car il gère la mémoire au niveau matériel avec le genre de complexité asynchrone qui produit ces fenêtres de timing.
L'impact confirmé au moment de la divulgation était l'exécution arbitraire de code, et la base de données Vulners signale également la corruption de données et les crashes du navigateur comme effets supplémentaires observés.
CVE-2026-5281 n'est pas apparue isolément. C'était la quatrième zero-day de Chrome en 2026, une année qui était déjà en passe de dépasser le total de huit zero-days de 2025 avant la fin du premier trimestre.
| Date | Événement |
|---|---|
| Février 2026 | CVE-2026-2441 corrigée, UAF dans le composant CSS de Chrome, exploitée activement |
| 10 mars 2026 | CVE-2026-3909 et CVE-2026-3910 corrigées, toutes deux des zero-days activement exploitées |
| 23 mars 2026 | CVE-2026-4675 (dépassement de tas WebGL) et CVE-2026-4676 (UAF dans Dawn) corrigées, même rapporteur que pour CVE-2026-5281 |
| 1er avril 2026 | Google publie Chrome 146.0.7680.177/178, 21 vulnérabilités corrigées, CVE-2026-5281 confirmée comme exploitée dans la nature |
| 1er avril 2026 | CISA ajoute CVE-2026-5281 au catalogue des vulnérabilités connues et exploitées |
| 3 avril 2026 | Google reconnaît une exploitation active visant 3,5 milliards d'utilisateurs de Chrome |
Le même chercheur pseudonyme qui a signalé CVE-2026-5281 a également signalé trois autres vulnérabilités dans la fenêtre de temps environnante (CVE-2026-4675, CVE-2026-4676, CVE-2026-5284, les deux dernières étant également des UAF dans Dawn). Cela suggère un effort de recherche ciblé et continu visant spécifiquement la gestion mémoire de Dawn.
La boîte à outils de ce dépôt est construite sur la base de recherches de sécurité originales documentant le comportement de la vulnérabilité dans un environnement de laboratoire. Ce qui suit est un résumé de ces recherches, de la stratégie utilisée pour déclencher l'UAF et des résultats observés.
L'approche du chercheur pour déclencher l'UAF a été conçue pour satisfaire simultanément les trois conditions qui rendent la fenêtre de course accessible : une pression suffisante sur la file d'attente GPU pour retarder l'exécution, un timing suffisamment serré entre le destroy et le dispatch, et une réallocation de buffers de même taille pour maximiser les chances de corruption observable.
La stratégie se décompose en cinq étapes :
Étape 1 - Volume et pression : 200 buffers de stockage WebGPU temporaires alloués avec des tailles aléatoires (toutes multiples de 4 octets, comme l'exige la spécification WebGPU). Il ne s'agit pas de remplir la VRAM, mais de créer suffisamment de travail en attente pour que le GPU ne puisse pas exécuter les commandes immédiatement.
Étape 2 - Saturation des threads de calcul : 32 pipelines de calcul parallèles mis en file d'attente avec des charges de travail lourdes, des boucles internes exécutant 1000 itérations et des tailles de dispatch de 4096 workgroups. L'objectif est de maintenir la file d'attente GPU profondément engorgée afin que la fenêtre entre la soumission et l'exécution reste ouverte assez longtemps pour faire la course.
Étape 3 - Le piège : Immédiatement après la soumission de tous les command buffers, destroy() est appelé sur les 200 buffers. À ce stade, le GPU a reçu les commandes mais ne les a pas encore exécutées. Dawn a déjà effectué sa validation au moment de la soumission. La VRAM est libérée.
Étape 4 - Le déclencheur : 32 nouvelles allocations de buffers utilisant exactement les mêmes tailles que les buffers qui viennent d'être libérés. Si l'allocateur de VRAM renvoie les mêmes adresses physiques, ce qui arrive souvent puisque les tailles correspondent, les commandes en attente du GPU disposent désormais d'un handle matériel pointant vers une mémoire qui appartient à une autre allocation, vivante celle-ci.
Étape 5 - Soumission de commandes de réutilisation : Une nouvelle série de soumissions de command buffers utilisant les buffers nouvellement alloués. À ce stade, deux ensembles de commandes dans la file référencent ce qui était autrefois la même mémoire, le GPU travaillant toujours sur le premier ensemble.
Le résultat est une UAF classique au niveau de la VRAM : de la mémoire libérée lue activement par une exécution de shader en vol.
Le chercheur a exécuté le PoC sur une installation Chrome vulnérable et sur une installation corrigée, et a observé une nette différence de comportement :
Exécution vulnérable (Chrome < 146.0.7680.178) :``` [INFO] CVE-2026-5281 AGGRESSIVE PoC Loaded [INFO] Initializing WebGPU context... [INFO] WebGPU device initialized [INFO] Starting aggressive UAF attacks... [ERROR] UNCAUGHT GPU ERROR: device lost due to internal error [CRASH] GPU DEVICE LOST: destroyed [CRASH] [!!!] CRASH DETECTED! Check console for details.
Le processus Chrome ciblé a complètement cessé le rendu. Le système d'exploitation a subi un bref gel visuel, cohérent avec le pilote d'affichage devant réinitialiser ou interrompre le traitement après le défaut GPU. L'événement de perte de périphérique a été mappé à une erreur GPU fatale plutôt qu'à une erreur de validation d'API WebGPU standard, ce qui confirme que la disposition mémoire corrompue a atteint la couche matérielle sans être interceptée par le sandboxing côté JavaScript de Chrome.
**Exécution corrigée (Chrome >= 146.0.7680.178) :**```
[INFO] CVE-2026-5281 AGGRESSIVE PoC Loaded
[INFO] Initializing WebGPU context...
[INFO] WebGPU device initialized
[INFO] Starting aggressive UAF attacks...
[INFO] Max attempts reached without crash
[INFO] Either browser is patched or target build not affected
Aucun crash, aucune perte de périphérique, aucun signal GPU fatal lors de toutes les tentatives. Le correctif tient.
Les captures suivantes ont été réalisées lors des tests en laboratoire de la boîte à outils contre une installation vulnérable et une installation corrigée de Chrome for Testing sur une machine Windows équipée d'un GPU intégré Intel gen-12lp. Chaque outil a été exécuté contre les deux cibles afin de vérifier la divergence de comportement.
01 - Détecteur de version
| Vulnérable (< 146.0.7680.178) | Corrigée (>= 146.0.7680.178) |
|---|---|
![]() | ![]() |
02 - Vérificateur de vulnérabilité
| Vulnérable | Corrigée |
|---|
![]() | ![]() |
03 - Scanner local
| Vulnérable | Corrigée |
|---|---|
![]() | ![]() |
04 - Scanner de parc
| Vulnérable | Corrigée |
|---|---|
![]() | ![]() |
05 - Déclencheur UAF
| Chrome | Firefox |
|---|---|
![]() | ![]() |
Firefox est inclus à titre de comparaison. Firefox utilise sa propre implémentation de WebGPU et n'est pas affecté par cette vulnérabilité. Il termine toutes les tentatives sans aucun signal de crash, quelle que soit la version, ce qui est le comportement attendu.
06 - Déclencheur UAF + Runner automatisé
| Perte du périphérique GPU |
|---|
![]() |
Obtenir un signal de crash visible n'est pas toujours simple. Selon le matériel et l'environnement, le déclencheur peut nécessiter un réglage fin pour produire des résultats observables. Dans notre cas, le comportement était reproductible, mais pas systématiquement mis en évidence sans ajuster la charge de travail.
Nous avons réussi à reproduire un déni de service contre une installation Chrome vulnérable dans un environnement de laboratoire contrôlé. Le déclencheur UAF provoque une saturation du GPU à 100 % d'utilisation, car la file de commandes fortement engorgée empêche le pilote de traiter les nouvelles requêtes de gestion mémoire. Lors de certaines exécutions, le processus GPU est entré dans un état de défaillance irrécupérable, produisant les effets observables suivants :
La saturation du GPU et l'exception occasionnelle confirment que la corruption mémoire atteint la couche matérielle : l'exécution de shaders en cours accède au handle du buffer libéré, le GPU déclenche une faute, et le mécanisme TDR de D3D12 la fait remonter comme un événement de retrait de périphérique. La version corrigée a exécuté la même charge de travail proprement, sans aucun signal de crash.
La reproduction du DoS confirme la vulnérabilité. Les travaux en cours sont axés sur l'analyse au niveau binaire du correctif, plus précisément sur le diff du chemin de soumission des command buffers de Dawn entre la dernière build vulnérable et la 146.0.7680.178, afin de comprendre exactement où et comment le correctif de comptage de références a été appliqué.
Concernant le runner automatisé : le chercheur d'origine a publié un script runner accompagnant son PoC. Notre version a nécessité des modifications pour fonctionner de manière fiable dans un contexte de laboratoire local, notamment le passage au nouveau mode headless de Chrome et l'ajout d'une option permettant aux signaux de crash GPU de se propager du processus GPU jusqu'au moteur de rendu. Sans ces deux options, Chrome absorbe silencieusement les crashes du processus GPU et la divergence de comportement entre les builds vulnérable et corrigée n'est pas observable depuis JavaScript.
Alors que les travaux de rétro-ingénierie et de diff binaire sont toujours en cours, le runner automatisé n'est pas publié dans ce dépôt. Il sera inclus dans une mise à jour ultérieure une fois l'analyse du correctif terminée.
Utilisez uniquement sur des systèmes qui vous appartiennent ou pour lesquels vous êtes explicitement autorisé à tester.