Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Upload Seguro de Arquivos no Node.js

Atualizado em: 8 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Uploads de arquivos são uma das superfícies mais perigosas de uma aplicação Node.js. Um arquivo pode ser grande demais, ter extensão enganosa, conter malware, explorar parsers, sobrescrever caminhos ou ser servido com um tipo executável. A proteção precisa acontecer antes, durante e depois do recebimento.

Defina a política

Antes do código, determine:

  • quais tipos são aceitos;
  • tamanho máximo;
  • quantidade por requisição;
  • quem pode enviar;
  • tempo de retenção;
  • se o arquivo será público;
  • processamentos necessários;
  • como será excluído.

Não confie no nome

Extensão e nome original são controlados pelo cliente. Gere um identificador:

import crypto from 'node:crypto';

const storageKey = crypto.randomUUID();

Guarde o nome original apenas como metadado redigido e limitado.

Limite de tamanho

Configure limite no proxy e no parser. Interrompa o stream assim que ultrapassar. Não leia o arquivo inteiro em memória.

const MAX_BYTES = 10 * 1024 * 1024;
let received = 0;

stream.on('data', (chunk) => {
  received += chunk.length;
  if (received > MAX_BYTES) {
    stream.destroy(new Error('Arquivo excede o limite'));
  }
});

Valide conteúdo real

O header Content-Type pode mentir. Inspecione magic bytes com biblioteca apropriada e compare com a allowlist. Mesmo assim, alguns formatos são complexos e exigem parser seguro.

Allowlist

Prefira uma lista curta, como JPEG, PNG e PDF. Bloquear extensões conhecidas é insuficiente porque novos formatos e combinações surgem.

Armazenamento fora da raiz pública

Não grave uploads em diretório servido automaticamente pelo framework. Use bucket privado ou pasta sem execução. A aplicação deve autorizar o download.

Nome e path

const safePath = path.join(UPLOAD_ROOT, storageKey);

Nunca combine o nome original diretamente. Verifique que o caminho final permanece dentro do diretório permitido.

Permissões

O processo deve ter apenas acesso necessário. Arquivos enviados não devem ser executáveis. Em containers, use volume dedicado e usuário sem privilégios.

Antivírus e sandbox

Arquivos de risco podem ser enviados para scanner assíncrono. Mantenha estado pending e não disponibilize até aprovação. Defina timeout, retry e quarentena.

Imagens

Decodifique e regrave com biblioteca atualizada, removendo metadados quando a política exigir. Limite dimensões e pixels para evitar decompression bombs.

PDF e documentos

PDFs podem conter scripts, anexos e links. Se a aplicação apenas exibe, considere conversão ou visualizador isolado. Não processe macros de documentos de escritório.

Arquivos compactados

ZIP pode conter zip slip e bombas de descompressão. Limite quantidade de entradas, tamanho descompactado total, profundidade e caminhos.

Download seguro

res.set({
  'Content-Type': storedMime,
  'Content-Disposition': `attachment; filename="${safeDownloadName}"`,
  'X-Content-Type-Options': 'nosniff',
});

Para conteúdo não confiável, attachment reduz execução no contexto da aplicação.

URLs assinadas

Em object storage, gere URLs de curta duração e escopo limitado. Não torne o bucket público. A autorização deve ocorrer antes da assinatura.

Status no banco

uploading -> pending_scan -> available
                         -> rejected

Estados explícitos evitam servir arquivos incompletos.

Transação e limpeza

Banco e storage não compartilham transação. Use compensação: se o banco falhar, exclua o objeto; se a exclusão falhar, registre job de limpeza.

Rate limiting e quota

Limite requisições, bytes por usuário, arquivos ativos e espaço total. Uma conta autenticada também pode ser comprometida.

CSRF

Uploads autenticados por cookie precisam de proteção CSRF. CORS não é suficiente.

Logs

Registre ID do upload, tamanho, tipo detectado, resultado do scanner e usuário. Não registre conteúdo nem nomes sensíveis sem necessidade.

Erros comuns

  • confiar em extensão;
  • usar nome original no path;
  • guardar em memória;
  • servir direto da pasta pública;
  • não limitar pixels ou descompressão;
  • disponibilizar antes do scan;
  • bucket público;
  • não limpar arquivos órfãos;
  • sem quota;
  • logs com conteúdo.

Fluxo recomendado

  1. autentique e autorize;
  2. aplique limites;
  3. gere ID interno;
  4. faça streaming;
  5. detecte tipo real;
  6. armazene em quarentena;
  7. escaneie e transforme;
  8. publique somente após aprovação;
  9. controle download;
  10. limpe órfãos.

Combine uploads com Streams e Backpressure, AbortController, CSRF, Rate Limiting e Audit Logs.

Consulte o guia de upload da OWASP e a documentação de Streams do Node.js.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita