tarfile no Python: crie TAR seguro

Publicado em: 17/08/2026
Tempo de leitura: 5 minutos
Close-up of a laptop screen with code and a coffee mug, perfect for tech abstract themes.

O módulo tarfile no Python cria, lê e extrai arquivos TAR, inclusive com compressão gzip, bzip2, XZ e, no Python 3.14, Zstandard quando o suporte está disponível. Diferentemente de GZIP, que representa um único fluxo, TAR funciona como contêiner: preserva caminhos, diretórios, permissões, timestamps, links e outros metadados do sistema de arquivos.

Esse poder também cria riscos. Um TAR malicioso pode tentar escrever fora do destino, criar links perigosos, dispositivos especiais ou milhares de arquivos. Desde o Python 3.14, o filtro de extração padrão é data, mais seguro que o comportamento antigo. Mesmo assim, filtros não impedem todos os ataques de negação de serviço e não substituem uma inspeção cuidadosa.

Quando usar tarfile

Use TAR para agrupar diretórios, backups, árvores de código e artefatos Unix. Para compartilhar arquivos com usuários de desktop, ZIP pode ser mais conveniente; veja como criar ZIP com Python. Para um único fluxo GZIP, use gzip no Python.

Crie um TAR sem compressão

import tarfile

with tarfile.open("projeto.tar", "x") as tar:
    tar.add("src", arcname="src")
    tar.add("README.md", arcname="README.md")

O modo x falha se o destino já existir, evitando sobrescrita. arcname controla o caminho armazenado e impede que diretórios absolutos locais apareçam no arquivo.

Crie TAR.GZ, TAR.BZ2 ou TAR.XZ

import tarfile

with tarfile.open("projeto.tar.gz", "x:gz", compresslevel=6) as tar:
    tar.add("src", arcname="src")

with tarfile.open("dados.tar.xz", "x:xz", preset=6) as tar:
    tar.add("dados", arcname="dados")

Os modos principais são w:gz, w:bz2, w:xz e w:zst. Use r:* para detectar automaticamente a compressão durante a leitura. Arquivos compactados não aceitam append tradicional; crie um novo arquivo quando precisar atualizar.

Liste membros sem extrair

import tarfile

with tarfile.open("projeto.tar.gz", "r:*") as tar:
    for membro in tar:
        print(membro.name, membro.size, membro.type)

Cada item é representado por TarInfo. Antes de extrair, examine nome, tipo, tamanho, destino de links e ocorrências duplicadas. isfile(), isdir(), issym(), islnk() e isdev() simplificam a classificação.

Extração segura no Python 3.14

O filtro padrão agora é data. Ainda assim, torne sua intenção explícita quando o código também precisa funcionar em versões anteriores:

import tarfile
from pathlib import Path

origem = Path("upload.tar.gz")
destino = Path("extracao").resolve()
destino.mkdir(parents=True, exist_ok=False)

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

O filtro bloqueia caminhos absolutos, caminhos que escapam do destino, links absolutos ou externos e arquivos especiais. Também reduz permissões e ignora proprietário e grupo.

O filtro data não resolve tudo

Um arquivo ainda pode conter milhões de membros, arquivos gigantes, nomes muito longos, duplicatas, colisões em sistemas sem distinção entre maiúsculas e minúsculas e conteúdo que esgota disco ou CPU. Extraia em diretório temporário novo, limite recursos no sistema operacional e remova o diretório inteiro se ocorrer falha.

Imponha quantidade e tamanho

import tarfile

MAX_ARQUIVOS = 5_000
MAX_TOTAL = 2 * 1024**3

def membros_validos(tar):
    total = 0
    for indice, membro in enumerate(tar, start=1):
        if indice > MAX_ARQUIVOS:
            raise ValueError("muitos membros")
        if membro.size < 0:
            raise ValueError("tamanho inválido")
        total += membro.size
        if total > MAX_TOTAL:
            raise ValueError("arquivo expandido excedeu o limite")
        if membro.isdev() or membro.isfifo():
            continue
        yield membro

with tarfile.open("upload.tar", "r:*") as tar:
    tar.extractall("destino", members=membros_validos(tar), filter="data")

O tamanho informado no cabeçalho também pode ser malicioso. Combine a verificação com cotas de disco e isolamento.

Mesmo links relativos válidos aumentam a complexidade. Um filtro personalizado pode ignorá-los:

import tarfile

def somente_dados(membro, caminho):
    membro = tarfile.data_filter(membro, caminho)
    if membro is None:
        return None
    if membro.issym() or membro.islnk():
        return None
    return membro

with tarfile.open("upload.tar.gz", "r:*") as tar:
    tar.extractall("destino", filter=somente_dados)

Filtros podem devolver um TarInfo modificado, devolver None ou lançar uma exceção.

Leia um arquivo sem extrair

extractfile() devolve um leitor binário para arquivos regulares e links compatíveis:

import tarfile
import json

with tarfile.open("pacote.tar.gz", "r:*") as tar:
    membro = tar.getmember("manifest.json")
    if not membro.isfile() or membro.size > 1_000_000:
        raise ValueError("manifesto inválido")
    with tar.extractfile(membro) as arquivo:
        manifesto = json.load(arquivo)

Essa abordagem é melhor quando você precisa apenas de um manifesto, configuração ou assinatura.

Evite caminhos locais no arquivo

tar.add() usa o caminho fornecido como nome padrão. Sempre defina arcname para obter estrutura portátil e não vazar diretórios internos.

Filtre durante a criação

import tarfile

def preparar(info):
    if info.name.endswith((".env", ".key")):
        return None
    info = info.replace(
        uid=0, gid=0, uname="root", gname="root",
        mtime=0,
    )
    return info

with tarfile.open("fonte.tar.gz", "x:gz", compresslevel=6) as tar:
    tar.add("projeto", arcname="projeto", filter=preparar)

Normalizar proprietário e timestamp ajuda a criar artefatos reproduzíveis. Confirme que segredos, caches, ambientes virtuais e arquivos temporários foram excluídos.

Formatos USTAR, GNU e PAX

  • USTAR_FORMAT: antigo e compatível, com limites de nome e tamanho.
  • GNU_FORMAT: extensões para nomes longos e arquivos grandes.
  • PAX_FORMAT: padrão atual, flexível e com metadados UTF-8.

PAX é o padrão para novos arquivos e costuma ser a melhor escolha.

Modo stream

Modos como r|gz e w|gz processam blocos sequencialmente, sem busca aleatória. Eles servem para stdin, stdout, sockets e pipes:

import sys
import tarfile

with tarfile.open(fileobj=sys.stdout.buffer, mode="w|gz", compresslevel=6) as tar:
    tar.add("resultado", arcname="resultado")

No modo stream, não tente voltar a membros anteriores. Planeje a ordem e processe cada item quando ele aparece.

Falhas podem deixar extração parcial

extractall() não desfaz o que já escreveu quando ocorre uma exceção. Extraia em diretório temporário exclusivo, valide o resultado e mova para o destino final somente após sucesso.

Erros importantes

Trate ReadError, CompressionError, StreamError e subclasses de FilterError. Não reduza errorlevel para zero em entradas externas, porque membros recusados podem ser apenas registrados e ignorados.

Testes essenciais

Inclua caminhos absolutos, ../, links externos, dispositivos, FIFOs, arquivos duplicados, muitos membros, arquivos enormes, nomes Unicode, TAR truncado e compressões diferentes. Teste em Windows e Linux quando portabilidade for necessária.

Boas práticas

  • Use r:* para leitura.
  • Use x para criação segura.
  • Defina arcname.
  • Extraia com filter="data".
  • Rejeite links se não forem necessários.
  • Limite membros, tamanho, nomes, disco e CPU.
  • Use diretório temporário novo.
  • Normalize metadados ao criar.
  • Não trate TAR como formato confiável.

Conclusão

O tarfile no Python é uma ferramenta completa para empacotar árvores de arquivos e combinar TAR com gzip, bzip2, XZ ou Zstandard. O Python 3.14 melhorou a segurança ao tornar data o filtro padrão, mas aplicações ainda precisam controlar links, quantidade, tamanho e isolamento.

Consulte a documentação oficial do tarfile e a PEP 706. Para investigar consumo durante grandes extrações, veja tracemalloc no Python.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Row of colorful office binders neatly arranged on a shelf, ideal for organization concepts.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    gzip no Python: comprima arquivos .gz

    Aprenda gzip no Python para ler e gravar .gz, criar saídas reproduzíveis, trabalhar com streams e limitar a expansão de

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    Color-coded office binders organized neatly in a storage shelf, featuring labels and a striking red binder.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    lzma no Python: comprima arquivos XZ

    Aprenda lzma no Python para criar arquivos XZ, usar streams, checks, filtros e limites de memória ao descompactar dados externos.

    Ler mais

    Tempo de leitura: 5 minutos
    17/08/2026
    Exquisite python skin handbag with intricate snake emblem and elegant design.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    bz2 no Python: comprima com bzip2

    Aprenda bz2 no Python para comprimir arquivos e bytes, processar fluxos em blocos e limitar a expansão de dados externos.

    Ler mais

    Tempo de leitura: 5 minutos
    16/08/2026
    Detailed view of programming code in a dark theme on a computer screen.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    zlib no Python: comprima dados

    Aprenda zlib no Python para comprimir e descomprimir bytes, processar streams, usar checksums e limitar dados externos.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Diagrama de arquivos e sistema representando configurações INI com configparser no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    configparser no Python: arquivos INI

    Aprenda configparser no Python para ler e gravar arquivos INI, usar defaults, interpolação, tipos e escrita atômica.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Módulo de memória RAM representando gerenciamento de objetos com gc no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    gc no Python: controle o coletor

    Aprenda gc no Python para controlar coleta cíclica, analisar objetos rastreados, diagnosticar vazamentos e observar pausas.

    Ler mais

    Tempo de leitura: 7 minutos
    16/08/2026