
Documente la chaîne RCE use-after-free de VectorFreed dans librsvg (CVE-2026-96889) avec un PoC de générateur SVG et des conseils de remédiation pour librsvg, Next.js et Satori.
Ce document présente « VectorFreed », une chaîne de vulnérabilités qui commence par un use-after-free que j'ai (@rafabd1) découvert dans librsvg (CVE-2026-96889). Dans une build Node.js/Sharp/libvips, ce bug a conduit à une exécution de commandes. Il couvre le bug, les chemins confirmés dans les applications jusqu'à présent, et les correctifs disponibles dès maintenant.
Un SVG peut inclure un autre SVG via XInclude. Dans le chemin vulnérable, librsvg commence à analyser un document inclus alors que libxml2 est encore en train de développer une entité dans le document externe. Si le SVG inclus déclare une entité portant le même nom, librsvg remplace et libère la première entité. libxml2 détient toujours un pointeur vers celle-ci.
Lorsque l'analyse du document inclus se termine, libxml2 poursuit avec cet ancien pointeur. La mémoire peut déjà appartenir à autre chose à ce moment-là, de sorte que des écritures ultérieures peuvent la corrompre. Un crash est l'un des résultats possibles. Dans d'autres cas, cela a également conduit à une exécution de commandes.
L'attaquant a besoin d'un balisage SVG crafté pour atteindre librsvg. Cela peut se produire lorsqu'une application accepte un fichier SVG, mais aussi lorsqu'une application construit un SVG à partir d'une entrée utilisateur. Le simple fait d'utiliser librsvg quelque part dans l'arbre de dépendances n'établit pas un chemin exploitable ; l'entrée doit atteindre une build affectée au moment du rendu de l'image.
La route Next.js que nous avons testée acceptait du texte au lieu d'un upload SVG. Elle plaçait ce texte à l'intérieur d'un SVG inline pour la version Node.js de ImageResponse. Un bug d'échappement distinct dans Satori permettait au texte de modifier le balisage SVG généré. Sharp/libvips transmettait ensuite ce SVG à librsvg. Vercel a suivi le chemin Next.js sous CVE-2026-94545. La version Edge de ImageResponse n'est pas affectée par ce chemin. Voici une courte reproduction Next.js.
Au cours de cette recherche, j'ai identifié des chemins d'entrée affectés dans plusieurs produits en aval et confirmé l'exécution de commandes dans plusieurs d'entre eux, y compris le cas Next.js décrit ci-dessus. La manière dont cette entrée atteint librsvg varie d'un produit à l'autre. C'est pourquoi un bug de parseur d'images en amont peut surgir dans des endroits qui ne semblent pas liés au premier abord ; le récent cas libheif en est un autre exemple. Cela ne signifie pas que tout produit utilisant librsvg est exploitable à distance.
ImageResponse. Mettez à niveau vers 16.3.6.Si vous utilisez les binaires précompilés de Sharp, vérifiez le paquet @img/sharp-libvips-* installé par votre application. Il embarque libvips et ses dépendances, y compris librsvg. Mettre à jour la copie système de librsvg peut laisser votre application utiliser l'ancienne.
Le PoC UAF inclut un générateur SVG pour plusieurs chemins d'entrée et peut être utilisé pour vérifier le use-after-free au début de la chaîne.
Jusqu'à présent, je n'ai pas trouvé d'exploit public qui mène cette chaîne de bout en bout, d'un SVG crafté jusqu'à l'exécution de commandes. Le bug et les correctifs sont toutefois déjà publics, et avec les outils d'IA actuels, il est assez facile de remonter à la chaîne complète à partir de ceux-ci. Compte tenu de cela, traitez l'exploit comme s'il était déjà public et mettez à jour les dépendances affectées ou atténuez le chemin d'entrée dès que possible.
[!WARNING] Il n'existe pas de PoC RCE universel pour cette chaîne ; la charge utile doit être adaptée à chaque cible. La plupart des « PoC » publics que j'ai vus jusqu'à présent ne reproduisent pas la véritable chaîne RCE. Certains s'appuient sur le
<foreignObject>SVG pour l'exécution revendiquée, ce qui n'est pas le chemin d'exploitation décrit ici.
Pour une validation initiale, le PoC UAF est plus pratique. Je prévois de publier un PoC RCE pour le cas Next.js (CVE-2026-94545) dans un dépôt séparé. Je publierai également l'analyse technique dans les semaines à venir, avec les étapes allant de l'UAF à l'exécution de commandes et un post-mortem couvrant ce mois passé de recherche sur la chaîne.