
Documenta o CVE-2026-65320, uma travessia de caminho tar-slip em untar_dir() do fastcore, com uma prova de conceito inofensiva que demonstra escrita arbitrária de arquivos e execução de código.
untar_dir()Severidade: Crítica, CVSS 3.1 9.8
Vetor (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Afetado: fastcore <= 2.2.30
Corrigido em: Não corrigido no momento da redação
CWE: CWE-22 (Limitação Imprópria de um Nome de Caminho a um Diretório Restrito, 'Path Traversal')
Componente: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()
Runtime de alto risco: Python < 3.14 (Python 3.14 torna o filtro tar data seguro o padrão)
Reportado por: Rahul Karne
CNA: VulnCheck
fastcore.xtras.untar_dir(fname, dest) é um helper documentado que extrai um arquivo tar "para dentro de dest".
Internamente, ele entrega o arquivo à função shutil.unpack_archive() da biblioteca padrão sem um filtro de extração, sem validar os caminhos dos membros do arquivo e sem qualquer verificação de contenção pós-extração.
Como resultado, um arquivo TAR cujos membros contenham sequências de travessia ../ ou caminhos absolutos pode gravar arquivos fora do diretório no qual o chamador pediu ao fastcore para extrair.
Um chamador que razoavelmente espera que untar_dir(fname, dest) confine tudo a dest em vez disso obtém gravação arbitrária de arquivos em qualquer lugar onde o processo possa gravar.
Gravação arbitrária de arquivos sob a autoridade do processo que chama untar_dir().
Dependendo do que for sobrescrito, isso pode resultar em:
A prova de conceito demonstra a cadeia completa gravação → importação → execução de código de ponta a ponta, inteiramente dentro de um diretório de demonstração inofensivo.
fastcore é uma dependência fundamental em todo o ecossistema fast.ai, incluindo:
fastainbdevghapiEle recebe dezenas de milhões de downloads por mês.
untar_dir() é a primitiva de extração por trás do fluxo de trabalho comum "baixar um arquivo, depois descompactá-lo", que segue o mesmo padrão geral do untar_data do fastai.
Qualquer caminho de código que forneça a untar_dir() um arquivo cujo conteúdo não seja totalmente confiável está exposto.
O código vulnerável existe em fastcore/xtras.py:
def _unpack(fname, out):
import shutil
shutil.unpack_archive(str(fname), str(out)) # <-- no filter, no validation
ls = out.ls()
return ls[0] if len(ls) == 1 else out
def untar_dir(fname, dest, rename=False, overwrite=False, uid=-1, gid=-1):
"untar `file` into `dest` ..."
import tempfile, shutil
dest = Path(dest)
with tempfile.TemporaryDirectory() as d:
out = Path(d) / remove_suffix(Path(fname).stem, '.tar')
out.mkdir()
...
src = _unpack(fname, out) # extraction escapes `out` here
...
shutil.move(str(src), dest)
...
return dest
untar_dir() cria um diretório temporário interno de extração:
<tempdir>/<random>/<archive-stem>/
Em seguida, chama _unpack(), que encaminha o arquivo diretamente para:
shutil.unpack_archive()
Para arquivos TAR, isso acaba chamando tarfile.extractall().
No Python < 3.14, o comportamento padrão de extração é fully_trusted, o que significa que membros com travessia podem ser aceitos.
Por exemplo, um membro de arquivo como:
../../../some/other/dir/file
é gravado em relação ao diretório de extração e, portanto, pode escapar dele.
Nada no fastcore:
filter="data" onde há suporte....untar_dir() trata shutil.unpack_archive() como se fosse um extrator de arquivos seguro e isolado.
Ele não é.
A documentação da biblioteca padrão do Python alerta que extrair arquivos não confiáveis pode criar arquivos fora do destino solicitado e recomenda filtragem segura de extração para arquivos TAR.
O fastcore nem passa um filtro de extração apropriado nem implementa uma proteção de contenção equivalente para as versões do Python que suporta.
Ele também não alerta os chamadores de untar_dir() sobre esse comportamento sensível à segurança.
Membros TAR podem conter strings de caminho arbitrárias.
Em versões afetadas do Python, tarfile.extractall() não neutraliza automaticamente sequências de travessia .. por padrão.
Gravar um membro com travessia em relação ao diretório temporário de extração do fastcore é, portanto, suficiente para escapar desse diretório e gravar em qualquer lugar onde o processo tenha permissão de gravação.
Uma primitiva confiável é a travessia relativa como:
../../../target/file
Esta é a técnica usada pela prova de conceito.
A entrada perigosa é o conteúdo do arquivo, não o caminho de destino escolhido pelo desenvolvedor.
Arquivos são frequentemente obtidos de locais externos ou semiconfiáveis, incluindo:
Qualquer serviço ou ferramenta que baixe um arquivo de uma fonte não confiável ou semiconfiável e subsequentemente o processe usando untar_dir() pode, portanto, estar acessível.
A PoC também inclui uma variante que serve o arquivo manipulado a partir de um endpoint HTTP controlado pelo atacante para demonstrar esse caminho de entrega.
A exploração bem-sucedida requer:
A aplicação chama fastcore.xtras.untar_dir() em um arquivo cujo conteúdo é influenciado pelo atacante, como um arquivo enviado, baixado ou de outra forma não confiável.
O runtime usa Python < 3.14, ou outra configuração onde um filtro seguro de extração TAR não é aplicado.
Para escalar de gravação arbitrária de arquivos para execução de código, o processo posteriormente importa ou carrega um arquivo de um local alcançável pela travessia, como:
Gravação arbitrária de arquivos e modificação de configuração/dados requerem apenas as condições 1 e 2.
poc_fastcore_cna_demo.py invoca a API real fastcore.xtras.untar_dir().
A demonstração é intencionalmente inofensiva.
Todo arquivo criado pela PoC permanece dentro de um único diretório de demonstração especificado usando:
--demo-root
A PoC não modifica arquivos reais do sistema e não acessa serviços de nuvem ou credenciais.
Imprime os detalhes do ambiente e o código-fonte vulnerável de _unpack() e untar_dir().
Cria um layout de demonstração contendo:
service_app/plugins/
Cria:
attacker_supplied_upload.tar
contendo membros de arquivo projetados para apontar fora da raiz de extração pretendida, incluindo membros com travessia e:
service_app/plugins/startup_hook.py
def auto_extract_uploaded_archive(received_archive):
return untar_dir(
received_archive,
intended_root,
overwrite=True
)
Verifica que arquivos foram gravados fora do diretório de extração pretendido.
Simula uma recarga do serviço importando o arquivo gravado pelo arquivo:
startup_hook.py
O hook de inicialização inofensivo cria:
SERVICE_RELOAD_MARKER
Isso demonstra a cadeia completa:
Attacker-controlled archive
↓
Path traversal during extraction
↓
Arbitrary file write
↓
Write into importable / auto-loaded location
↓
Application loads attacker-controlled file
↓
Code execution
Instale o pacote afetado:
pip install fastcore
O problema foi confirmado através de:
fastcore 2.2.30
A demonstração pode ser executada contra:
fastcore instalada via pip--sourceTodas as gravações da PoC permanecem dentro do diretório especificado através de --demo-root.
Limpe qualquer saída anterior da PoC:
python poc_fastcore_cna_demo.py --demo-root ./poc_fastcore --clean
Execute a demonstração:
python poc_fastcore_cna_demo.py \
--demo-root ./poc_fastcore \
--source latest \
--no-pause
Exemplo de saída abreviada:
fastcore version: 2.2.30
Outside marker exists after extraction? True
Is outside marker inside intended extraction root? False
Relative traversal marker exists after extraction? True
Is relative traversal marker inside intended extraction root? False
Service plugin file exists after extraction? True
Service reload marker exists? True
POC WORKED: fastcore extracted attacker-controlled tar members outside the intended root.
Em versões suportadas do Python, use um filtro de extração seguro como:
filter="data"
com shutil.unpack_archive() ou a operação de extração tarfile correspondente.
Cada membro do arquivo deve ser verificado antes da extração.
Rejeite:
..Os destinos dos links também devem ser resolvidos e validados antes da extração.
Resolva cada caminho de destino antes de gravar e verifique se ele permanece abaixo da raiz de extração pretendida.
Conceitualmente:
resolved_member_path
↓
must remain inside
↓
resolved_extraction_root
A extração deve falhar se o destino resolvido escapar da raiz de extração.
Os testes de regressão devem cobrir pelo menos:
../ traversal
absolute paths
Windows drive-letter paths
UNC paths
symbolic links
hard links
Documente claramente se untar_dir() tem a intenção de processar com segurança arquivos não confiáveis.
Se a extração insegura for intencionalmente suportada, o comportamento seguro ainda deve ser o padrão.
O comportamento inseguro deve exigir opt-in explícito em vez de confiar silenciosamente no conteúdo do arquivo.
Até que uma correção no nível do pacote seja lançada:
untar_dir().O defeito técnico subjacente é uma vulnerabilidade de gravação arbitrária de arquivos causada por travessia de caminho em arquivos.
No entanto, a severidade final depende do ambiente de implantação e de como untar_dir() é exposto.
Um vetor representativo pode se aproximar de:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Resultado:
9.8 — Critical
Se a exploração em vez disso exigir que um desenvolvedor baixe e extraia manualmente um arquivo, a interação do usuário e a complexidade do ataque podem ser maiores.
A pontuação CVSS resultante seria, portanto, materialmente menor.
Dois fatores importantes devem ser considerados ao avaliar o problema.
Esta é uma instância da classe de vulnerabilidade de extração insegura de TAR conhecida há muito tempo, associada a:
CVE-2007-4559
Versões modernas do Python introduziram comportamento mais seguro de extração de arquivos.
Python 3.14 torna o filtro de extração data seguro o padrão.
Portanto, o ambiente primário afetado é o Python < 3.14.
No entanto, esses runtimes permanecem amplamente implantados.
A vulnerabilidade se torna explorável quando um chamador fornece a untar_dir() um arquivo cujo conteúdo é controlado pelo atacante ou de outra forma não confiável.
Este relatório, portanto, trata o conteúdo do arquivo como a fronteira de segurança não confiável.
Um helper robusto de extração de arquivos deve falhar com segurança independentemente de como o arquivo foi obtido.
Substitua as datas de placeholder abaixo pelas datas reais de divulgação.
YYYY-MM-DD — Vulnerabilidade reportada aos mantenedores.YYYY-MM-DD — Resposta do fornecedor / confirmação / sem resposta.2.2.30); o código de extração permaneceu inalterado.Descoberto e reportado por Rahul Karne.
Documentação de untar_dir() do fastcore
https://fastcore.fast.ai/xtras.html
Código-fonte de xtras.py do fastcore
https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/xtras.py
fastcore no PyPI
https://pypi.org/project/fastcore/
Documentação de shutil.unpack_archive() do Python
https://docs.python.org/3/library/shutil.html#shutil.unpack_archive
Filtros de extração do tarfile do Python
https://docs.python.org/3/library/tarfile.html#extraction-filters
PEP 706 — Filtro para tarfile.extractall
https://peps.python.org/pep-0706/
CWE-22 — Limitação Imprópria de um Nome de Caminho a um Diretório Restrito
https://cwe.mitre.org/data/definitions/22.html
CVE-2007-4559 — Classe de vulnerabilidade de extração insegura de TAR
https://nvd.nist.gov/vuln/detail/CVE-2007-4559
Este repositório documenta uma descoberta de segurança de divulgação coordenada e fornece uma prova de conceito inofensiva e autocontida.
A PoC grava apenas dentro do diretório --demo-root especificado pelo usuário e não realiza ações destrutivas.
Qualquer funcionalidade de rede incluída na demonstração é limitada a uma demonstração local opcional.
Este material é fornecido para pesquisa de segurança defensiva e fins educacionais.
Consultas da mídia: [email protected]. PoC completa (servidor do atacante, arquivo de travessia, aplicação vítima) e detalhes técnicos adicionais disponíveis sob solicitação.