tarfile extraction_filter: extraia TAR com segurança

Publicado em: 08/10/2026
Tempo de leitura: 6 minutos
Arquivos protegidos representando extração segura de TAR com Python

Arquivos TAR aparecem em backups, pacotes de software, pipelines de dados, imagens de contêineres e processos de implantação. O módulo tarfile do Python facilita a leitura e a extração desses arquivos, mas extrair conteúdo vindo de uma fonte externa exige cuidado. Um arquivo malicioso pode tentar gravar dados fora da pasta de destino, criar links perigosos, alterar permissões ou sobrescrever arquivos importantes. O recurso extraction_filter existe para tornar esse processo mais explícito e seguro.

Neste guia, você aprenderá como usar filtros de extração, como escolher uma política adequada, como criar um filtro personalizado e quais verificações devem ser feitas antes de aceitar um arquivo TAR em produção.

Por que a extração de TAR exige validação

Um membro de arquivo TAR possui nome, caminho, tipo, permissões, usuário, grupo, tamanho e, em alguns casos, destino de link. Esses metadados podem ser manipulados. Um nome como ../../config.php tenta escapar da pasta de destino. Um caminho absoluto pode apontar diretamente para uma área sensível do sistema. Links simbólicos também podem redirecionar a escrita para fora do diretório esperado.

Por isso, nunca trate um TAR desconhecido como se fosse apenas uma coleção inocente de arquivos. A extração deve ser uma operação controlada, com destino isolado, limites de tamanho, política de nomes e revisão dos tipos permitidos.

O papel de extraction_filter

O atributo TarFile.extraction_filter permite definir uma política aplicada aos membros durante a extração. O filtro recebe informações sobre o membro e pode aceitar, modificar ou rejeitar a entrada. Em vez de espalhar verificações manuais pelo código, você centraliza a política em um ponto claro e reutilizável.

O Python oferece filtros conhecidos, como políticas mais permissivas para compatibilidade e políticas mais restritivas para dados comuns. Em aplicações modernas, a escolha deve favorecer a opção mais segura compatível com o seu caso de uso.

from pathlib import Path
import tarfile

arquivo = Path("backup.tar.gz")
destino = Path("dados_extraidos")
destino.mkdir(parents=True, exist_ok=True)

with tarfile.open(arquivo, "r:gz") as tar:
    tar.extractall(destino, filter="data")

O filtro data é uma escolha adequada quando o objetivo é extrair arquivos de dados comuns e evitar características perigosas ou desnecessárias de um arquivo de sistema completo.

Filtro data, tar e fully_trusted

A política data tenta produzir uma extração apropriada para dados, removendo ou recusando aspectos arriscados. A política tar preserva mais características tradicionais do formato. Já fully_trusted representa uma postura permissiva e só deve ser considerada quando a origem é realmente confiável e o arquivo foi produzido dentro de um ambiente controlado.

Na prática, prefira data para uploads, integrações, downloads e arquivos recebidos de terceiros. Use opções mais permissivas apenas quando houver uma necessidade técnica clara, revisão do conteúdo e isolamento suficiente.

Criando um filtro personalizado

Alguns projetos precisam aceitar apenas arquivos regulares, impedir executáveis ou limitar extensões. Um filtro personalizado permite expressar essas regras.

from pathlib import Path
import tarfile

EXTENSOES = {".csv", ".json", ".txt"}

def filtro_dados(member, path):
    nome = Path(member.name)

    if member.isdir():
        return member

    if not member.isfile():
        return None

    if nome.suffix.lower() not in EXTENSOES:
        return None

    if member.size > 20 * 1024 * 1024:
        return None

    return member.replace(mode=0o600)

with tarfile.open("entrada.tar") as tar:
    tar.extractall("saida", filter=filtro_dados)

Nesse exemplo, diretórios são aceitos, arquivos especiais são descartados, apenas três extensões são permitidas, cada arquivo deve ter no máximo 20 MB e as permissões são normalizadas. A função retorna None quando o membro deve ser ignorado.

Verifique o tamanho total

Limitar apenas o tamanho individual não impede um arquivo composto por milhares de entradas pequenas. Antes de extrair, some os tamanhos declarados e imponha um limite total. Também defina um número máximo de membros.

MAX_ARQUIVOS = 5000
MAX_TOTAL = 500 * 1024 * 1024

with tarfile.open("entrada.tar") as tar:
    membros = tar.getmembers()

    if len(membros) > MAX_ARQUIVOS:
        raise ValueError("Muitos arquivos no TAR")

    total = sum(m.size for m in membros if m.isfile())
    if total > MAX_TOTAL:
        raise ValueError("Tamanho total excedido")

    tar.extractall("saida", members=membros, filter="data")

Esses limites ajudam a reduzir risco de esgotamento de disco, memória e tempo de processamento.

Extraia em diretório isolado

Evite extrair diretamente em uma pasta usada pela aplicação. Crie um diretório temporário, faça a validação e mova apenas os arquivos aprovados para o destino final. Esse fluxo reduz o impacto de nomes inesperados e evita misturar dados incompletos com arquivos ativos.

Depois da extração, percorra o diretório resultante, confirme os tipos, valide o conteúdo e registre métricas. Para dados estruturados, tente abrir e analisar cada arquivo antes de promovê-lo.

Links merecem atenção especial porque o caminho aparente pode ser seguro enquanto o destino aponta para outro local. Quando o projeto não precisa de links, rejeite todos. Essa política simples elimina uma classe importante de problemas.

def sem_links(member, path):
    if member.issym() or member.islnk():
        return None
    return tarfile.data_filter(member, path)

Você pode combinar sua própria regra com um filtro padrão. Assim, aproveita a proteção existente e adiciona as restrições específicas do projeto.

Tratamento de erros

Não ignore exceções de extração. Registre o nome do arquivo, a etapa, o motivo da rejeição e o identificador da operação. Porém, não exponha caminhos internos ou detalhes sensíveis ao usuário final.

import tarfile

try:
    with tarfile.open("entrada.tar") as tar:
        tar.extractall("saida", filter="data")
except tarfile.TarError as erro:
    raise RuntimeError("Arquivo TAR inválido ou inseguro") from erro

Também remova o diretório temporário quando a operação falhar, evitando resíduos e resultados parciais.

Boas práticas para produção

Use listas de permissões de extensões, imponha limites individuais e totais, rejeite arquivos especiais, normaliza permissões, extraia em área temporária e mantenha logs. Execute a extração com um usuário sem privilégios e, para cargas não confiáveis, considere um contêiner ou processo isolado.

Não use apenas a extensão do TAR para decidir se ele é seguro. Valide o formato, o conteúdo e o contexto. Um arquivo com nome correto ainda pode ter metadados perigosos.

Compatibilidade entre versões

Ao manter bibliotecas compatíveis com diferentes versões do Python, teste se o parâmetro filter está disponível e documente o comportamento mínimo aceito. Evite criar uma falsa sensação de segurança em ambientes antigos. Se a aplicação depende dessa proteção, estabeleça uma versão mínima do Python.

Testes recomendados

Crie testes com caminhos relativos normais, caminhos com .., caminhos absolutos, links, arquivos grandes, muitos membros, extensões bloqueadas e permissões incomuns. Confirme que o diretório final permanece vazio quando a validação falha.

Você também pode revisar outros conteúdos da Academify sobre zipfile.Path no Python, os.path.splitroot, pathlib.Path.info e sqlite3 autocommit. Para referência oficial, consulte a documentação do tarfile e as orientações do pathlib.

Conclusão

tarfile extraction_filter transforma a extração em uma operação governada por política. Em vez de confiar cegamente nos metadados do arquivo, você decide quais membros, caminhos, tamanhos, tipos e permissões são aceitáveis. Para a maioria dos arquivos externos, comece com filter="data", adicione limites e use um diretório temporário. Essa combinação oferece uma base muito mais segura e previsível para processar TAR no Python.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python em tela representando inspeção de módulos e pacotes
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    inspect.ispackage: identifique pacotes Python

    Aprenda inspect.ispackage no Python para identificar pacotes, explorar módulos e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 5 minutos
    05/10/2026
    Notebook exibindo código e gráficos de desempenho para análise do sys._jit no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sys._jit: detecte e meça o JIT experimental

    Aprenda sys._jit no Python para detectar suporte ao JIT experimental, medir desempenho e evitar decisões frágeis.

    Ler mais

    Tempo de leitura: 6 minutos
    05/10/2026