Varredura de vírus para uploads de arquivos: opções de arquitetura para apps
Varredura de vírus para uploads de arquivos explicada para apps com muitos documentos: armazenamento em quarentena, filas de scan, controle de acesso, retries e fluxos seguros de liberação.

O problema em termos simples: arquivos inseguros entrando no seu app
Se o seu app permite que pessoas façam upload de documentos, você está aceitando arquivos que não criou. Em produtos com muitos documentos (portais de clientes, sistemas de RH, apps de sinistros, onboarding de fornecedores), uploads são frequentes e os usuários costumam compartilhar arquivos vindos de e-mails, drives compartilhados ou terceiros. Isso torna esses apps um alvo prático: um upload bem-sucedido pode se espalhar por muitos downloads.
Os riscos não são apenas “um vírus”. Um arquivo Word ou Excel pode conter macros maliciosas, um PDF pode ser criado para explorar falhas do leitor, e uma “fatura” pode ser um documento de phishing que induz alguém a ligar para um número falso ou inserir credenciais. Alguns arquivos são envenenados de maneiras mais silenciosas, como esconder uma carga em um ZIP, usar extensões duplas (report.pdf.exe) ou incorporar conteúdo remoto que “phone home” ao ser aberto.
Confiar em um antivírus simples instalado em um servidor não é suficiente. Uploads podem atingir várias instâncias do app, mover-se entre sistemas de armazenamento ou ser servidos a partir de object storage ou CDN. Se qualquer caminho de código expuser o upload bruto, usuários podem baixá-lo antes que o scan termine. Atualizações, configurações incorretas e acessos administrativos “temporários” também podem, com o tempo, contornar a verificação.
O objetivo claro para a varredura de vírus em uploads de arquivos é simples: nenhum arquivo não verificado deve ser baixável ou visualizável por quem não esteja explicitamente autorizado a revisar conteúdo em quarentena.
Defina o que “seguro” significa como uma regra de negócio, não como uma sensação. Por exemplo:
- Deve passar na varredura de malware com um conjunto de assinaturas atualizado
- Deve corresponder aos tipos de arquivo e limites de tamanho permitidos
- Deve ser armazenado e servido apenas de locais aprovados
- Deve ter trilha de auditoria: quem fez o upload, quando e status final
- Deve ficar bloqueado até uma decisão final: liberar ou rejeitar
Se você constrói com uma plataforma como AppMaster, trate o “status do scan” como um campo de primeira classe no seu modelo de dados e faça cada ação de download verificá-lo. Esse único gate previne muitos erros caros.
O que quarentena realmente significa para documentos enviados
“Quarentena” é melhor entendida como um estado no seu sistema, não apenas uma pasta no armazenamento. A ideia chave é simples: o arquivo existe, mas ninguém pode abri-lo ou baixá-lo até que seu app tenha um resultado de scan claro e registrado. Isso é o coração da varredura de vírus para uploads de arquivos.
Quarentena geralmente funciona como um pequeno ciclo de vida com status claros. Manter o estado explícito torna mais difícil vazar conteúdo inseguro por meio de preview, URL direto ou job de exportação.
Um conjunto prático de estados de arquivo fica assim:
- received (upload concluído, ainda não verificado)
- scanning (pego por um worker)
- clean (seguro para liberar)
- rejected (malware encontrado ou violação de política)
- failed (erro do scanner, timeout ou arquivo corrompido)
Quarentena também precisa dos metadados certos para que você possa aplicar acesso e auditar o que aconteceu depois. No mínimo, armazene: o proprietário (usuário ou organização), status, nome e tipo originais do arquivo, checksum (para deduplicação e checagens de alteração), localização no armazenamento e timestamps (upload, início do scan, fim do scan). Muitas equipes também registram a versão do scanner e os detalhes do veredito.
Retenção é uma decisão de política, mas deve ser intencional. Mantenha arquivos em quarentena apenas pelo tempo necessário para escaneá-los e depurar falhas. Retenção curta reduz risco e custo, mas você ainda precisa de tempo suficiente para investigar incidentes e dar suporte a usuários que perguntam “onde foi meu upload?”.
Por fim, decida o que fazer com arquivos que nunca terminam o scan. Defina um tempo máximo de scan e um timestamp de “expiração”. Quando o prazo passa, mova o arquivo para failed, bloqueie acesso e ou tente novamente automaticamente um número limitado de vezes ou exclua e solicite que o usuário reenvie.
Padrões de armazenamento temporário que reduzem risco
É no armazenamento temporário que a maioria dos problemas de upload acontece. O arquivo está no seu sistema, mas ainda não se sabe se é seguro, então você precisa de um lugar fácil de bloquear e difícil de expor por acidente.
Disco local pode funcionar para um único servidor, mas é frágil. Se você escala para vários servidores de app, precisa compartilhar armazenamento, copiar arquivos e manter permissões consistentes. Object storage (como um bucket estilo S3 ou um container na nuvem) é muitas vezes mais seguro para apps com muitos documentos porque regras de acesso são centralizadas e logs ficam mais claros.
Um padrão simples para varredura de vírus em uploads é separar “quarentena” de armazenamento “limpo”. Você pode fazer isso com dois buckets/containers, o que torna erros menos prováveis, ou com um prefixo estrito dentro de um único bucket, o que pode ser mais barato e fácil de gerenciar.
Se usar prefixes, torne-os impossíveis de confundir. Prefira um layout como quarantine/<tenant_id>/<upload_id> e clean/<tenant_id>/<document_id>, não nomes fornecidos pelo usuário. Nunca reutilize o mesmo caminho para diferentes estados.
Mantenha estas regras em mente:
- Não permita leitura pública na quarentena, mesmo “temporariamente”.
- Gere nomes de objetos no servidor, não nomes do cliente.
- Particione por tenant ou conta para reduzir o raio de dano.
- Armazene metadados (proprietário, status, checksum) no seu banco, não no filename.
Criptografe em repouso e seja rígido sobre quem pode descriptografar. A API de upload deve conseguir escrever na quarentena, o scanner deve conseguir ler da quarentena e escrever no clean, e o app público deve apenas ler do clean. Se sua nuvem suporta políticas de chave, vincule direitos de descriptografia ao menor conjunto possível de papéis.
Arquivos grandes exigem cuidado extra. Para uploads multipart, não marque o objeto como “pronto” até a última parte ser confirmada e você ter registrado o tamanho esperado e checksum. Uma abordagem segura comum é fazer upload das partes na quarentena e depois copiar ou promover o objeto para o clean somente após o scan passar.
Exemplo: em um portal de clientes construído com AppMaster, você pode tratar todo upload como “pending”, armazená-lo em um bucket de quarentena e só mostrar o botão de download depois que o resultado do scan mudar o status para “clean”.
Opções de arquitetura: scan inline vs scan em background
Ao adicionar varredura de vírus para uploads de arquivos, normalmente você escolhe entre dois fluxos: scan inline (o usuário espera) ou scan em background (o app aceita o upload mas bloqueia acesso até liberar). A escolha certa depende menos do “nível de segurança” (ambos podem ser seguros) e mais de velocidade, confiabilidade e de quão frequentes são os uploads.
Opção 1: Scan inline (usuário espera)
Scan inline significa que a requisição de upload não termina até o scanner retornar um resultado. Parece simples porque há apenas um passo: upload, scan, aceitar ou rejeitar.
Scan inline costuma ser aceitável quando arquivos são pequenos, uploads raros e você consegue manter o tempo de espera previsível. Por exemplo, uma ferramenta interna onde usuários enviam alguns PDFs por dia pode tolerar uma pausa de 3 a 10 segundos. O lado negativo é que um scan lento torna o app lento. Timeouts, retries e redes móveis podem transformar um arquivo limpo em uma má experiência de usuário.
Opção 2: Scan em background (assíncrono)
Scan assíncrono armazena o arquivo primeiro, marca-o como “quarentenado” e envia um job para uma fila de scan. O usuário recebe uma resposta rápida de “upload recebido”, mas não pode baixar ou visualizar o arquivo até que ele seja liberado.
Essa abordagem é melhor para volumes altos, arquivos maiores e horários de pico porque distribui o trabalho e mantém o app responsivo. Também permite escalar os workers de scan separadamente dos servidores web ou API.
Um híbrido prático é: executar checagens rápidas inline (allowlist de tipos de arquivo, limites de tamanho, validação básica de formato) e fazer o scan antivírus completo em background. Isso captura problemas óbvios cedo sem fazer todo usuário esperar.
Aqui está uma maneira simples de escolher:
- Arquivos pequenos, baixo volume, fluxos que precisam saber imediatamente: scan inline
- Arquivos grandes, muitos uploads ou tempo de scan imprevisível: scan em background
- SLAs rígidos para responsividade do upload: scan em background + UI de status clara
- Workloads mistos: híbrido (checagens rápidas primeiro, scan completo async)
Se você usa AppMaster, essa escolha costuma mapear bem para um endpoint síncrono de API (inline) ou um Business Process que enfileira trabalho de scan e atualiza o status do arquivo quando os resultados chegam.
Passo a passo: construindo uma fila de scan assíncrona
Scan assíncrono significa que você aceita um upload, o tranca em quarentena e o verifica em segundo plano. Usuários não têm acesso até o scanner dizer que é seguro. Esse é geralmente o modelo mais prático para apps com muitos documentos.
1) Defina a mensagem da fila (mantenha pequena)
Trate a fila como uma lista de tarefas. Cada upload cria uma mensagem que aponta para o arquivo, não o arquivo em si.
Uma mensagem simples geralmente inclui:
- File ID (ou object key) e tenant ou project ID
- ID do usuário que enviou
- Timestamp de upload e checksum (opcional mas útil)
- Número de tentativas (ou um contador de retry separado)
Evite colocar bytes brutos na fila. Payloads grandes podem estourar limites, custar mais e aumentar exposição.
2) Construa o fluxo do worker (buscar, escanear, registrar)
Um worker puxa uma mensagem, busca o arquivo na quarentena, faz o scan e escreve de volta uma decisão.
Um fluxo claro é:
- Buscar arquivo por ID no armazenamento de quarentena (bucket privado ou volume privado)
- Rodar o scanner (motor AV ou serviço de varredura)
- Escrever o resultado no banco: status (clean, infected, error), nome/versão do scanner e timestamps
- Em clean: mover o arquivo para armazenamento aprovado ou alterar uma flag de acesso para que vire baixável
- Em infected: manter em quarentena (ou deletar) e notificar as pessoas certas
3) Torne idempotente (seguro para reprocessar)
Workers vão travar, mensagens são entregues duas vezes e retries vão ocorrer. Desenhe para que escanear o mesmo arquivo duas vezes não cause dano. Use um registro fonte única como files.status e permita apenas transições válidas, por exemplo: uploaded -> scanning -> clean/infected/error. Se um worker ver clean, deve parar e reconhecer a mensagem.
4) Controle concorrência (evite tempestades de scan)
Defina limites por worker e por tenant. Limite quantos scans podem rodar ao mesmo tempo e considere filas separadas para arquivos grandes. Isso impede que um cliente ocupadíssimo consuma toda a capacidade do scanner.
5) Trate falhas com retries e trilha de auditoria
Use retries para erros temporários (timeout do scanner, problema de rede) com um número máximo de tentativas pequeno. Depois disso, envie a mensagem para uma dead-letter queue para revisão manual.
Mantenha uma trilha de auditoria: quem fez o upload, quando entrou em quarentena, qual scanner rodou, o que decidiu e quem aprovou ou deletou o arquivo. Esse log é tão importante quanto a varredura em si, especialmente para portais de clientes e conformidade.
Controle de acesso: mantendo arquivos em quarentena realmente privados
Quarentena não é apenas um status no banco. É uma promessa de que ninguém pode abrir o arquivo até que esteja provado seguro. A regra mais segura é simples: nunca sirva arquivos em quarentena por URLs públicos, mesmo “temporárias”.
Um bom fluxo de download é chato e estrito. O app deve tratar todo download como uma ação protegida, não como buscar uma imagem.
- Requisitar download
- Verificar permissão do usuário para aquele arquivo específico
- Checar o status do arquivo (quarentenado, clean, rejected)
- Entregar o arquivo apenas se o status for clean
Se usar signed URLs, mantenha a mesma ideia: gere-as somente após checar permissão e status, e faça-as com curta duração. Expiração curta reduz danos se o link vazar por logs, screenshots ou um e-mail encaminhado.
Controle baseado em função ajuda a evitar lógica de “casos especiais” que vira buraco. Papéis típicos para apps com muitos documentos são:
- Uploader: vê seus próprios uploads e status de scan
- Reviewer: pode ver arquivos limpos e, às vezes, ver arquivos em quarentena apenas em uma ferramenta de revisão segura
- Admin: pode investigar, re-scanner e sobrescrever acesso quando necessário
- Usuário externo: só acessa documentos explicitamente compartilhados com ele
Também proteja contra adivinhação de IDs. Não exponha IDs incrementais como 12345. Use IDs opacos e sempre autorize por usuário e por arquivo (não apenas “qualquer usuário logado”). Mesmo que seu bucket seja privado, um endpoint descuidado ainda pode vazar conteúdo em quarentena.
Quando você constrói varredura de vírus para uploads de arquivos, a camada de acesso é onde a maioria das falhas reais acontece. Numa plataforma como AppMaster, você aplicaria essas checagens nos endpoints da API e na lógica de negócio antes de gerar qualquer resposta de download, assim a quarentena permanece privada por padrão.
Liberar, rejeitar e tentar novamente: lidando com resultados do scan
Quando um arquivo termina de ser escaneado, o mais importante é movê-lo para um estado claro e tornar o próximo passo previsível. Se você está implementando varredura de vírus para uploads de arquivos, trate o resultado do scan como um portão: nada vira baixável até que o portão permita.
Um conjunto simples de desfechos cobre a maioria dos sistemas:
- Clean: liberar o arquivo da quarentena e permitir acesso normal.
- Infected: bloquear acesso permanentemente e acionar workflow de arquivo infectado.
- Unsupported: o scanner não consegue avaliar esse tipo (ou está protegido por senha). Mantê-lo bloqueado.
- Scan error: falha temporária (timeout, serviço indisponível). Mantê-lo bloqueado.
A comunicação ao usuário deve ser clara e calma. Evite termos alarmantes como “Sua conta está comprometida.” Uma abordagem melhor é: “O arquivo está sendo verificado. Você pode continuar trabalhando.” Se o arquivo for bloqueado, diga o que o usuário pode fazer a seguir: “Envie outro tipo de arquivo” ou “Tente novamente mais tarde.” Para arquivos não suportados, seja específico (por exemplo, “Arquivos compactados com senha não podem ser escaneados”).
Para arquivos infectados, decida cedo se vai deletar ou reter. Deletar é mais simples e reduz risco. Reter pode ajudar auditorias, mas somente se for em uma área isolada com acesso estrito e retenção curta, e você registrar quem pode vê-lo (idealmente, ninguém exceto admins de segurança).
Retries são úteis, mas apenas para erros que provavelmente são temporários. Defina uma política de retry pequena para não criar backlog infinito:
- Repetir em timeouts e indisponibilidade do scanner.
- Não tentar novamente em caso de “infected” ou “unsupported”.
- Limitar retries (por exemplo, 3) e depois marcar como failed.
- Adicionar backoff entre tentativas para evitar sobrecarga.
Por fim, trate falhas repetidas como um problema de ops, não do usuário. Se muitos arquivos chegarem a “scan error” num curto período, alerte sua equipe e pause novas liberações. No AppMaster, você pode modelar esses estados no banco e rotear notificações pelos módulos de mensagens para que as pessoas certas sejam avisadas rapidamente.
Cenário de exemplo: um portal de clientes com muitos documentos
Um portal de clientes deixa clientes enviar faturas e contratos por projeto. É um lugar comum onde a varredura de vírus para uploads importa, porque usuários arrastam o que está no desktop, incluindo arquivos encaminhados por outras pessoas.
Quando um cliente envia um PDF, o portal salva em uma localização temporária e privada e cria um registro no banco com status definido como Pending scan. O arquivo não é mostrado como baixável ainda. Um worker de scan puxa o arquivo de uma fila, faz a verificação e atualiza o registro para Clean ou Blocked.
Na interface, o cliente vê o documento aparecer imediatamente, mas com um selo claro de Pending. O nome do arquivo e tamanho ficam visíveis para que saiba que o upload funcionou, mas o botão de Download fica desabilitado até o scan ficar clean. Se o scan demorar mais que o esperado, o portal pode mostrar uma mensagem simples como “Estamos verificando este arquivo por segurança. Tente novamente em um minuto.”
Se o scanner sinalizar um documento, o cliente vê Blocked com uma nota curta e não técnica: “Este arquivo falhou em uma verificação de segurança.” Suporte e admins têm uma visão separada com motivo do scan e próximos passos. Eles podem:
- manter bloqueado e solicitar um novo upload
- deletar e registrar o motivo
- marcar como falso positivo apenas se a política permitir
Em disputas (“Enviei ontem e vocês perderam”), bons logs importam. Mantenha timestamps de upload recebido, início do scan, fim do scan, mudança de status e quem fez o quê. Também guarde hash do arquivo, nome original, conta que enviou, IP e código de resultado do scanner. Se você constrói isso no AppMaster, o Data Designer mais um Business Process simples podem gerenciar esses status e campos de auditoria sem expor arquivos em quarentena a usuários comuns.
Erros comuns que causam brechas reais de segurança
A maioria das falhas em segurança de upload não são hacks sofisticados. São pequenas decisões de design que permitem que um arquivo inseguro se comporte como um documento normal.
Um problema clássico é uma corrida (race): o app aceita um upload, devolve uma URL de download e o usuário (ou outro serviço) consegue buscar o arquivo antes do scan terminar. Se você faz varredura de vírus para uploads, trate “uploaded” e “available” como dois estados diferentes.
Aqui estão erros que aparecem repetidamente:
- Misturar arquivos limpos e em quarentena no mesmo bucket/pasta e confiar em regras de nomeação. Uma permissão errada ou um caminho confuso torna a quarentena inútil.
- Confiar em extensão de arquivo, MIME type ou checagens do lado cliente. Atacantes podem renomear qualquer coisa para .pdf e sua UI não vai perceber.
- Não planejar downtime do scanner. Se o scanner estiver lento ou offline, arquivos podem ficar “pending” para sempre e equipes começam a criar overrides manuais inseguros.
- Deixar workers de background pularem as mesmas regras de autorização que a API principal. Um worker que pode ler “qualquer arquivo” é uma escalada silenciosa de privilégio.
- Publicar IDs fáceis de adivinhar (como números incrementais) para itens em quarentena, mesmo que você ache que o conteúdo está protegido.
Testes também são um gap. Equipes testam com alguns arquivos pequenos e limpos e consideram pronto. Você também precisa testar uploads grandes, arquivos corrompidos e documentos protegidos por senha, porque são exatamente onde scanners e parsers falham ou dão timeout.
Um exemplo simples: um usuário faz upload de “contract.pdf” que na verdade é um executável renomeado dentro de um arquivo. Se seu portal o entrega instantaneamente, ou seu time de suporte pode acessar a quarentena sem checagens, você criou um caminho direto para distribuir o conteúdo a outros usuários.
Checklist rápido antes do lançamento
Antes de lançar a varredura de vírus para uploads de arquivos, faça uma última checagem nos lugares onde equipes supõem “está ok” e depois descobrem que não estava. O objetivo é simples: um arquivo inseguro não deve se tornar legível só porque alguém adivinhou uma URL, refez uma requisição ou usou um link antigo em cache.
Comece pelo fluxo do usuário. Qualquer ação de download, preview ou “abrir arquivo” deve checar o status atual do scan no momento da requisição, não apenas no upload. Isso protege contra condições de corrida, resultados de scan atrasados e casos onde um arquivo é re-scaneado.
Use esta checklist mínima antes do envio:
- Armazenamento de quarentena é privado por padrão: sem bucket público, sem “qualquer um com o link” e sem servir direto do object storage.
- Cada registro de arquivo tem um proprietário (usuário, equipe ou tenant) e um estado de ciclo de vida claro como pending, clean, infected ou failed.
- Sua fila de scan e workers têm retries limitados, regras de backoff claras e alertas quando itens travam ou falham repetidamente.
- Logs de auditoria existem para uploads, resultados de scan e tentativas de download (incluindo bloqueadas), com quem, quando e por quê.
- Override manual existe para casos raros, mas é admin-only, registrado e com tempo limitado (sem botão “marcar limpo” silencioso).
Por fim, assegure que você pode observar o sistema de ponta a ponta. Você deve conseguir responder: “Quantos arquivos estão pendentes de scan agora?” e “Quais tenants estão vendo falhas?” Se você constrói no AppMaster, modele o ciclo de vida dos arquivos no Data Designer e aplique checagens de estado no Business Process Editor para que as regras sejam consistentes entre web e mobile.
Próximos passos: transformar o design em um app funcional
Comece escrevendo os estados exatos que seus arquivos podem ter e o que cada estado permite. Mantenha simples e explícito: “uploaded”, “queued”, “scanning”, “clean”, “infected”, “scan_failed”. Depois, adicione regras de acesso próximas a cada um. Quem pode ver o arquivo, baixá-lo ou deletá-lo enquanto ainda é não confiável?
Em seguida, escolha a abordagem que combina com seu volume e metas de experiência. Scan inline é mais fácil de explicar, mas pode deixar uploads lentos. Scan assíncrono escala melhor para apps com muitos documentos, mas adiciona estado, filas e UI de “pending”.
Uma forma prática de ir do design para a construção é prototipar todo o fluxo fim a fim usando documentos realistas (PDFs, arquivos Office, imagens, arquivos compactados) e comportamento realista do usuário (múltiplos uploads, cancelar, retries). Não pare em “o scanner funciona”. Valide que o app nunca serve um arquivo em quarentena, mesmo por acidente.
Aqui está um plano simples que você pode executar em uma semana:
- Definir estados de arquivo, transições e regras de acesso em uma página
- Escolher inline, async ou híbrido para varredura de vírus em uploads e documentar tradeoffs
- Implementar upload -> armazenamento de quarentena -> job de scan -> callback de resultado, com logs de auditoria
- Construir as telas de UI que usuários verão (pending, blocked, failed, approved)
- Adicionar monitoramento desde o primeiro dia: tamanho do backlog, taxa de falhas e tempo até limpar
Se você está construindo sem código, AppMaster pode ajudar a modelar metadados do arquivo (status, proprietário, checksum, timestamps), montar telas de upload e revisão e orquestrar o fluxo de scan com lógica de negócio e processamento em estilo fila. Isso permite testar o fluxo real do produto cedo e então endurecer as partes que importam: permissões, separação de armazenamento e retries confiáveis.
Finalmente, decida metas numéricas. Defina thresholds de alerta antes do lançamento, para que você note scans travados e falhas crescentes antes que os usuários percebam.


