Arquivos de modelo e de workflow costumam atravessar a empresa como se fossem dados: entram por um bucket, passam por um registry e terminam num job com acesso a GPU, datasets e credenciais de nuvem. A CVE-2025-33214 mostra o erro dessa premissa. No NVIDIA NVTabular, carregar um workflow serializado podia executar código no mesmo processo que fazia a carga.
O problema não exige quebrar CUDA nem explorar a GPU. A fronteira falha antes disso, na desserialização de um arquivo workflow.pkl com cloudpickle. Se alguém consegue substituir, publicar ou indicar um artefato que outra pessoa ou automação carregará, o conteúdo deixa de ser apenas configuração e passa a ter a autoridade da identidade que executa o pipeline.

O que a CVE-2025-33214 confirma
A NVIDIA atribuiu CVSS 3.1 de 8,8, severidade alta, com vetor AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. Em termos práticos, a entrada pode chegar pela rede e a exploração tem baixa complexidade e não exige privilégio prévio, mas depende de uma ação da vítima: o workflow malicioso precisa ser carregado. O impacto potencial inclui execução de código, indisponibilidade, exposição e adulteração de dados.
- Produto afetado: NVIDIA NVTabular em Linux
- Componente vulnerável: carregamento de Workflow
- Versão testada pelo GitHub Security Lab: v23.08.00
- Abrangência oficial: todas as versões que não incluem o commit 5dd11f4
- Causa classificada: CWE-502, desserialização de dados não confiáveis
A linha em que dado vira execução
O método Workflow.load resolve o caminho com fsspec e abre workflow.pkl. Na implementação analisada pelo GitHub Security Lab, o objeto era entregue diretamente a cloudpickle.load. Pickle não é um formato passivo: durante a reconstrução, ele pode importar classes e chamar funções. Por isso, conferir extensão ou nome, ou apenas calcular um hash sem uma referência confiável, não muda a natureza do arquivo.
# Vulnerable implementation documented by GitHub Security Lab
workflow = cloudpickle.load(
fs.open(fs.sep.join([path, "workflow.pkl"]), "rb")
)
# Fix in commit 5dd11f4
from nvtabular.tools.serialization import load as load_safe
workflow = load_safe(
fs.open(fs.sep.join([path, "workflow.pkl"]), "rb")
)A correção adiciona um Unpickler próprio e sobrescreve find_class. Quando o pickle tenta reconstruir uma classe ou função fora da lista permitida, a carga termina com erro. É uma diferença pequena no ponto de chamada, mas muda a pergunta de segurança de 'o que este arquivo quer importar?' para 'esta importação foi explicitamente autorizada?'.

O vetor real é a cadeia de artefatos
O CVSS registra interação do usuário porque alguém ou algum job precisa carregar o workflow. Isso não reduz o cenário a phishing manual. Em ambientes de ML, a ação pode ser um notebook aberto por um pesquisador, uma promoção automática entre buckets, um job de validação ou um serviço que recebe o caminho do modelo. O teste relevante é descobrir quem pode gravar ou apontar o artefato e qual identidade o consome.
- Registry ou bucket permite publicação por identidades que não deveriam influenciar produção
- Pipeline promove artefatos sem assinatura, proveniência ou hash fixado
- Notebook compartilhado carrega workflows de diretórios graváveis por outros usuários
- Job de inferência ou preparação de dados roda com credenciais mais amplas que o necessário
- Logs registram a execução do job, mas não o digest e a origem exata do artefato carregado
Como testar sem executar um pickle malicioso
Num pentest, não precisamos colocar uma carga de execução num ambiente compartilhado para provar o risco. Primeiro confirmamos a versão do código e o ponto de carga por inspeção estática. Depois mapeamos permissões de escrita e leitura do registry, identidade do consumidor e promoção entre ambientes. Uma prova segura pode usar um artefato inválido e inerte para demonstrar que uma origem sem confiança alcança o loader, sem incluir opcode capaz de chamar o sistema operacional.
# Run in the NVTabular checkout used to build the image.
# These commands only read code and Git history.
rg -n 'cloudpickle\.load|load_safe' nvtabular/workflow/workflow.py
if git merge-base --is-ancestor 5dd11f4 HEAD; then
echo 'fix 5dd11f4 is present in history'
else
echo 'fix 5dd11f4 was not confirmed in this checkout'
fi
git rev-parse HEADEncontrar load_safe é evidência útil, mas não encerra a análise. O binário ou contêiner em produção precisa corresponder ao código revisado, e a lista de classes permitidas também merece inspeção. Em desserialização, cada nova classe autorizada amplia novamente a superfície disponível durante a reconstrução.
Correção e contenção
A orientação oficial é atualizar para uma branch que inclua o commit 5dd11f4 ou posterior. A NVIDIA não identifica uma versão numerada corrigida no boletim, então conferir apenas a versão exibida pelo pacote pode ser insuficiente. É preciso validar o commit incorporado, a imagem de contêiner aprovada ou a confirmação equivalente fornecida pelo mantenedor da distribuição usada.
- Atualize o NVTabular para código que contenha 5dd11f4 ou posterior e reconstrua as imagens derivadas
- Invalide workflows de origem desconhecida e republique artefatos a partir de um pipeline confiável
- Exija digest imutável, assinatura e proveniência antes da promoção para produção
- Separe quem publica artefatos de quem autoriza sua execução em ambientes privilegiados
- Reduza credenciais, mounts e acesso de rede do processo que carrega workflows
- Registre digest, origem, identidade publicadora e identidade consumidora em cada carga
A lição para qualquer pipeline de ML
CVE-2025-33214 é específica do NVTabular, mas o padrão é maior: modelo, checkpoint e workflow serializado podem conter comportamento, não só pesos ou configuração. Se o processo de ingestão confia na extensão do arquivo e o processo de execução confia no loader, a cadeia inteira delega execução a quem controla o artefato.
Um pentest desse ambiente precisa seguir o caminho completo do objeto, da publicação ao runtime. A pergunta decisiva não é apenas 'o pacote está corrigido?', mas 'quem consegue fazer este processo privilegiado carregar o quê?'. É nessa ligação entre storage, identidade, automação e runtime que uma falha de desserialização vira comprometimento de infraestrutura.