FlawOpen

flawopen.com/Desserialização insegura/Segurança do pickle em Python

O pickle.load() do Python é seguro para dados não confiáveis?

CWE-502: Desserialização de Dados Não ConfiáveisPágina de referência
Resposta curta

Não. Trate o pickle como um programa dentro de uma encomenda, não como um registro passivo: carregá-lo pode acionar a reconstrução antes de a aplicação validar o objeto. Use um formato somente de dados para entradas que cruzam uma fronteira de confiança.

INSEGURO — bytes não confiáveis podem acionar código ao carregar
import pickle

# Never accept pickle bytes from a request, upload,
# shared cache, or other untrusted source.
obj = pickle.loads(untrusted_bytes)
ALTERNATIVA MAIS SEGURA — analise os dados e valide o esquema
import json

def parse_profile(raw: bytes) -> dict[str, str]:
    if len(raw) > 65_536:
        raise ValueError("Payload too large")

    try:
        value = json.loads(raw)
    except (json.JSONDecodeError, UnicodeDecodeError):
        raise ValueError("Invalid JSON") from None

    if not isinstance(value, dict) or set(value) - {"display_name", "theme"}:
        raise ValueError("Invalid profile")

    name = value.get("display_name")
    theme = value.get("theme")
    if not isinstance(name, str) or len(name) > 80:
        raise ValueError("Invalid display name")
    if theme not in {"light", "dark"}:
        raise ValueError("Invalid theme")

    return {"display_name": name, "theme": theme}
Fluxo pickle:
Sequência de bytes específica do Python que descreve a reconstrução de objetos, incluindo referências a globais e comportamento de reconstrução.
Unpickling:
Interpretação do fluxo e reconstrução do grafo de objetos; o processo pode invocar funções.
Fronteira de confiança:
Ponto em que bytes podem ser controlados ou alterados por usuário, serviço, upload ou armazenamento compartilhado.
CWE-502:
Desserialização de dados não confiáveis; o impacto depende de um atacante poder fornecer ou adulterar os dados carregados.
Etapa 1

Bytes não confiáveis chegam ao pickle

Um upload, solicitação, cache ou artefato pode levar dados pickle controlados ou adulterados até o processo.

Etapa 2

O unpickler resolve globais

O interpretador processa instruções de reconstrução; find_class() pode importar e retornar globais nomeados, inclusive funções.

Etapa 3

O carregamento aciona comportamento

As instruções podem invocar funções durante load() ou loads(), antes da validação do objeto retornado.

Etapa 4

O impacto depende das permissões do processo

O comportamento executa com as permissões do processo Python. Rede, segredos, arquivos e isolamento determinam o alcance.

Por que o carregamento do pickle cruza uma fronteira de execução de código

Um fluxo pickle pode nomear globais e funções de reconstrução. Durante o unpickling, Unpickler.find_class() resolve globais, inclusive funções; opcodes podem invocar a reconstrução. O passo perigoso é pickle.load() ou pickle.loads(): não existe uma chamada posterior separada para executar. O código resultante usa as permissões do processo. Esse comportamento faz parte do formato; não use pickle para intercambiar dados não confiáveis.

O que JSON resolve — e o que não resolve

A documentação do Python alerta que unpickling de dados não confiáveis ou adulterados pode executar código arbitrário, enquanto decodificar JSON não cria, por si só, essa via de execução. JSON não valida a entrada automaticamente: limite o tamanho, exija o tipo superior e os campos esperados, valide valores com um esquema e aplique autorização separadamente. Se um fluxo legado ainda precisar de pickle, autentique os bytes exatos com uma chave protegida antes de carregar; uma assinatura só comprova origem e integridade sob as premissas da chave e não torna seguro um conteúdo malicioso assinado por fonte confiável. Migre para formato somente de dados.

Perguntas frequentes

Um Unpickler restrito torna seguro o pickle controlado por atacante?

Sobrescrever find_class() pode reduzir riscos restringindo globais, mas provar que um loader é seguro em todos os protocolos e comportamentos alcançáveis é difícil. Não trate uma lista de permissões como defesa padrão para bytes controlados pelo usuário; prefira formato somente de dados.

JSON também precisa de validação?

Sim. JSON evita a execução arbitrária de código típica do pickle durante a decodificação, mas a aplicação ainda deve validar tipos, campos, tamanhos, limites e autorização. Separe análise JSON das regras de negócio.

Referências primárias

Veja também Desserialização insegura: riscos e correção Ruby YAML.load é seguro? Versões do Psych e safe_load .NET BinaryFormatter: riscos e migração ObjectInputStream Java: desserialização segura Newtonsoft.Json TypeNameHandling: configuração segura? PHP unserialize() e entrada não confiável