A regra de ouro: nunca confiar em dados externos

Todo dado que entra no sistema por uma fronteira externa é potencialmente malicioso ou incorreto

Validação e sanitização são a primeira linha de defesa de qualquer aplicação. Todo dado que chega de fora — input de formulário, parâmetros de URL, payload de API, arquivo enviado por usuário, resposta de API externa, mensagem de fila — deve ser tratado como potencialmente malicioso ou incorreto até que seja validado. A principal razão para a maioria das vulnerabilidades de segurança conhecidas (SQL injection, XSS, command injection, path traversal) é a falha em validar e sanitizar inputs antes de usá-los. Um único campo de texto que chega direto ao banco de dados sem validação pode comprometer todo o sistema.

Validação versus sanitização — conceitos distintos

Validar é verificar; sanitizar é transformar

Validação verifica se o dado é válido para o propósito: o email tem formato correto? A idade é um número inteiro positivo? O CPF tem dígitos verificadores válidos? Se o dado não passa na validação, a operação é rejeitada com erro explicativo. Sanitização transforma o dado para remover ou escapar partes potencialmente problemáticas: remover tags HTML de um campo de texto, converter entidades HTML para escapar XSS, remover caracteres de controle, normalizar encoding. Validação e sanitização são complementares e frequentemente necessárias juntas. A ordem importa: sanitize antes de validar, ou valide o formato antes de sanitizar, dependendo do contexto.

SQL Injection — a vulnerabilidade que nunca some

Como dados não validados destroem o banco de dados

SQL injection acontece quando input do usuário é concatenado diretamente em uma query SQL em vez de usar parametrização. O clássico: username = "admin' OR '1'='1" em uma query SELECT * FROM users WHERE username = '$username' retorna todos os usuários porque a condição OR '1'='1' sempre é verdadeira. Variações mais destrutivas incluem DROP TABLE, exfiltração de dados via UNION e execução de comandos do sistema operacional via xp_cmdshell. A solução não é validar o input para bloquear aspas — é usar sempre queries parametrizadas (prepared statements) onde o banco trata o input como dado, nunca como parte da query. ORMs modernos usam parametrização por padrão.

XSS — injetando scripts em páginas vistas por outros usuários

Como texto não sanitizado vira código executável no browser

Cross-Site Scripting (XSS) ocorre quando input do usuário é renderizado em HTML sem escapar as tags. Se um usuário inserir um script malicioso em um campo de comentário e esse texto for renderizado diretamente no HTML, o script executa no browser de todos os outros usuários que virem o comentário. Consequências vão de roubo de cookie de sessão (comprometendo contas) a phishing dentro do site. A solução é escapar HTML em todo dado renderizado dinamicamente: converter os caracteres especiais em entidades HTML. Frameworks modernos como React, Angular e Vue escapam por padrão — mas funções de renderização raw como dangerouslySetInnerHTML (React) ou innerHTML (JS puro) bypassam essa proteção.

Command Injection e Path Traversal

Inputs que se tornam comandos do sistema operacional ou caminhos de arquivo

Command injection ocorre quando input do usuário é passado para execução de comandos do sistema (shell). Se uma API aceita um nome de arquivo como parâmetro e executa convert $filename.pdf $filename.png sem validar, um input de "file; rm -rf /" executa dois comandos — o convert e o rm. Path traversal ocorre quando input do usuário é usado para construir caminhos de arquivo: /download?file=../../../etc/passwd navega para fora do diretório permitido e acessa arquivos do sistema. A defesa é: nunca passar input externo diretamente para execução de sistema; usar whitelist de valores válidos para nomes de arquivo; resolver o caminho absoluto e verificar que ele está dentro do diretório permitido.

Validação em múltiplas camadas — frontend e backend

Validação no frontend é UX; validação no backend é segurança

Validação no frontend melhora a experiência do usuário: feedback imediato sobre campos inválidos sem precisar de um round-trip ao servidor. Mas validação no frontend nunca é suficiente para segurança — qualquer desenvolvedor pode contornar validação JavaScript usando DevTools, Postman ou curl. A validação de segurança deve sempre acontecer no backend, onde o código é confiável. A regra é: validar no frontend para UX, validar novamente no backend para segurança. Nunca assumir que um dado que passou pela validação do frontend é automaticamente válido no backend.

Validação de tipos e schemas

Garantir que os dados têm a forma esperada antes de processar

Validação de schema verifica a estrutura completa do dado recebido: campos obrigatórios presentes, tipos corretos (string onde string é esperado, número onde número é esperado), formatos válidos (email, UUID, data ISO), e intervalos aceitáveis (preço positivo, idade entre 0 e 150). Bibliotecas de validação como Zod (TypeScript), Joi (Node.js), FluentValidation (.NET) e Pydantic (Python) permitem definir schemas declarativos e validar dados de forma expressiva e reutilizável. Data Annotations no .NET e Bean Validation no Java integram validação diretamente nos models e são executadas automaticamente pelo framework antes do handler da requisição.

Sanitização de HTML — quando aceitar markup é necessário

Editores de texto rico exigem sanitização rigorosa do HTML recebido

Editores de texto rico (WYSIWYG) enviam HTML ao servidor — o que é necessário para formatação mas também o principal vetor de XSS persistente. A solução não é rejeitar HTML completamente (se o produto requer formatação rica) mas sanitizar rigorosamente: usar uma whitelist de tags e atributos permitidos e remover tudo mais. Bibliotecas como DOMPurify (JavaScript, client e server), bleach (Python) e HtmlSanitizer (.NET) implementam sanitização segura baseada em whitelist. Nunca implemente sanitização de HTML manualmente com expressões regulares — é impossível cobrir todos os vetores de ataque.

Validação de uploads de arquivo

Arquivos são uma das superfícies de ataque mais exploradas

Uploads de arquivo exigem validação múltipla: verificar o tipo real do arquivo pelo conteúdo binário (magic bytes), não apenas pela extensão ou Content-Type declarado pelo cliente; limitar o tamanho máximo; verificar que o conteúdo não contém executável malicioso (para imagens, usar bibliotecas de processamento de imagem que reprocessam o arquivo em vez de servir o original diretamente); armazenar em diretório separado fora do webroot; e nunca executar código baseado no conteúdo do arquivo. Verificar magic bytes: JPEG começa com FF D8 FF, PNG com 89 50 4E 47, PDF com 25 50 44 46 — um arquivo renomeado como image.jpg mas com conteúdo PHP não passa nessa verificação.

Conclusão — validação e sanitização são o contrato do sistema com o mundo externo

Dados não validados são o ponto de entrada de praticamente toda vulnerabilidade crítica

Validação e sanitização são a primeira camada de segurança de qualquer aplicação. A regra fundamental: toda entrada de dados de qualquer fonte externa deve ser validada antes de ser processada e sanitizada antes de ser renderizada. Use frameworks de validação em vez de regex manual, queries parametrizadas em vez de concatenação, e whitelists em vez de blacklists. Segurança por profundidade aplica: validação no frontend, validação no backend, queries parametrizadas no banco, e sanitização na renderização. Continue em: Fundamentos obrigatórios antes de produção.

Validação, Sanitização e Segurança — Vídeos

Conceitos-chave

SQL Injection

Vulnerabilidade onde input externo é inserido diretamente em query SQL — prevenido com queries parametrizadas.

XSS

Cross-Site Scripting: input renderizado como HTML sem escape executa código malicioso no browser do usuário.

Prepared Statements

Queries com placeholders que o banco trata como dado, nunca como código SQL — prevenção padrão de SQL injection.

Whitelist vs Blacklist

Whitelist (permitir apenas o que é explicitamente válido) é mais seguro que blacklist (bloquear o que é inválido).

Magic Bytes

Primeiros bytes do arquivo que identificam seu tipo real — mais confiável que extensão ou Content-Type para validação.

DOMPurify

Biblioteca de sanitização de HTML baseada em whitelist — a escolha padrão para aceitar HTML de usuários de forma segura.

Sistemas Distribuídos no Instagram

@bytebytego

Reels — Arquitetura e Backend

@bytebytego

ByteByteGo no Facebook

Sistemas em Produção no X

@mjovanovictech

Como testar resiliência de sistemas em produção real

Ver post completo no X →
@mjovanovictech

Padrões de resiliência em .NET Core com exemplos

Ver post completo no X →
@mjovanovictech

Arquitetura de software orientada a domínio

Ver post completo no X →
@mjovanovictech

Lições de 5 anos mantendo sistemas em produção

Ver post completo no X →
@mjovanovictech

Design de APIs resilientes para produção

Ver post completo no X →
@mjovanovictech

Microsserviços vs monolito — como escolher

Ver post completo no X →

O que dizem

Priya S. ★★★★★

O ponto sobre validação no frontend ser apenas UX é frequentemente ignorado por juniores. Tivemos um pentest que bypaseou toda validação JavaScript e enviou payloads direto à API sem nenhum problema. Validação no backend é obrigatória e o artigo explica isso muito bem.

Andre L. ★★★★★

O exemplo de magic bytes para validação de upload é exatamente o que precisava. Tínhamos apenas verificação de extensão e um usuário enviou um PHP renomeado como image.jpg. Verificar os primeiros bytes do arquivo é simples de implementar e efetivo.

Sofia T. ★★★★☆

Ótimo artigo. Uma adição: ao usar ORMs como Hibernate ou Entity Framework, o mapeamento automático protege de SQL injection, mas concatenação de strings em queries JPQL ou LINQ bypassam essa proteção. É preciso usar parâmetros nomeados mesmo em ORMs.