Regex seguro: como validar formatos sem sofrer ReDoS
Aprenda a escrever um regex seguro para validar formatos de entrada e proteger seu sistema contra ataques ReDoS. Teste sua expressão com nosso testador!

Implementar um regex seguro é um passo crucial no desenvolvimento de software para validar dados de entrada com segurança e evitar falhas críticas no sistema. As expressões regulares (regex) são recursos extremamente eficientes para verificar formatos de entrada como e-mails, telefones e códigos postais. Contudo, se a estrutura de um padrão for projetada de maneira descuidada, ela pode deixar as aplicações vulneráveis a ataques de Negação de Serviço por Expressão Regular, conhecidos internacionalmente pela sigla ReDoS (Regular Expression Denial of Service).
Neste artigo, analisaremos detalhadamente o funcionamento de um ReDoS, os riscos do backtracking catastrófico, como inspecionar seus padrões e quais são as práticas recomendadas para mitigar esse risco de desempenho.
O que é Backtracking Catastrófico?
Para entender por que um regex mal estruturado pode representar um risco de segurança digital, é necessário compreender o funcionamento interno dos motores de regex tradicionais. A maioria das linguagens de programação (como JavaScript, Python, PHP e C#) utiliza motores baseados em Autômatos Finitos Não Determinísticos (NFA). Esses motores realizam a validação utilizando uma abordagem de "tentativa e erro", chamada backtracking (retrocesso).
Quando um motor NFA tenta validar um padrão de texto e encontra múltiplos caminhos possíveis, ele escolhe um deles e segue em frente. Caso o caminho escolhido falhe no final da cadeia de caracteres, o motor retrocede à última escolha disponível para tentar a alternativa seguinte. Se o padrão regex for mal desenhado e o texto enviado pelo usuário for malicioso, o número de caminhos possíveis crescerá exponencialmente. Esse cenário é chamado de backtracking catastrófico.
// Exemplo clássico de padrão vulnerável em JavaScript
const regexVulneravel = /^([a-zA-Z0-9]+)*$/;
const inputMalicioso = "a".repeat(30) + "!";
console.time("Execução do Regex");
regexVulneravel.test(inputMalicioso);
console.timeEnd("Execução do Regex");
// A validação levará segundos ou minutos para concluir,
// travando o thread de execução principal do Node.js.
Se um invasor identificar este regex vulnerável em um formulário público ou em um endpoint de API, ele poderá enviar um payload especificamente montado. Em plataformas single-threaded, como Node.js, isso travará o servidor por completo, saturando a CPU em 100% e impedindo que requisições legítimas sejam atendidas.
Anatomia de um Regex Vulnerável a ReDoS
As expressões regulares vulneráveis a ReDoS exibem padrões estruturais muito claros. O problema central quase sempre decorre de quantificadores aninhados ou grupos com sobreposição de correspondência, que impedem o motor de determinar com clareza uma única correspondência por caractere.
Aqui estão os três tipos de estruturas vulneráveis mais frequentes:
- Quantificadores Aninhados: Padrões como
(a+)+ou([a-zA-Z0-9]+)*onde um grupo que já possui quantificador interno é englobado por outro quantificador externo. - Alternâncias Sobrepostas: Padrões como
(a|a)+ou(\w+|[a-zA-Z]+)+onde o motor pode interpretar o mesmo caractere de várias formas distintas em diferentes ramificações. - Prefixos e Sufixos Sobrepostos: Estruturas como
\w+\d+\w+aplicadas sobre entradas longas que não contêm o delimitador final esperado, forçando o motor a computar todas as permutações possíveis.
Comparativo de Motores de Regex: NFA vs. DFA
Nem todos os motores de expressões regulares correm riscos de sofrer ataques ReDoS. A segurança do sistema depende diretamente do tipo de algoritmo implementado: motores NFA (tempo exponencial mas com suporte a recursos complexos como retroreferências e lookarounds) ou DFA (Autómatos Finitos Determinísticos, que validam em tempo linear mas possuem sintaxe mais restritiva).
| Motor / Biblioteca | Tipo de Algoritmo | Tempo de Execução | Vulnerável a ReDoS | Recomendação de Uso |
|---|---|---|---|---|
| V8 (JS / Node.js) | NFA | Exponencial | Sim | Validações padrão com limites severos de entrada. |
Python re |
NFA | Exponencial | Sim | Processamento de texto onde a entrada é de confiança. |
Go regexp (RE2) |
DFA | Linear | Não | Serviços concorrentes expostos a entradas de terceiros. |
Rust regex |
DFA / Híbrido | Linear | Não | Sistemas de alto desempenho e segurança crítica. |
| .NET Regex Engine | NFA (com Timeouts) | Exponencial (configurável) | Sim (Mitigado por timeouts) | Aplicações corporativas que podem limitar o tempo de computação. |
Como demonstrado na tabela comparativa, motores como RE2 do Google (padrão em Go e disponível para Node.js/Python via pacotes externos) eliminam o backtracking catastrófico garantindo complexidade $O(N)$ em tempo linear, embora fiquem limitados pela falta de suporte para lookarounds e backreferences.
Estratégias de Mitigação e Práticas Recomendadas
Garantir a proteção das suas APIs contra ReDoS exige uma combinação de escrita cuidadosa dos padrões regex e restrições práticas.
1. Evitar sobreposições e aninhamentos complexos
Ao escrever uma expressão regular, certifique-se de que cada caractere do texto de entrada tenha apenas um caminho lógico correspondente. Em vez de utilizar padrões como ^(\w+\s*)+$, adote uma estrutura fechada e delimitada como ^\w+(?:\s+\w+)*$.
2. Validar o comprimento da string antes do Regex
O backtracking exponencial necessita de textos de entrada longos para se tornar prejudicial. Se você está validando um CEP de 8 dígitos ou um e-mail curto, verifique o comprimento da string antes de executar a validação de regex. Se a string exceder o limite aceitável, rejeite-a de imediato.
function validarEntrada(entrada: string): boolean {
// 1. Limite de tamanho estrito
if (entrada.length > 50) {
return false;
}
// 2. Execução do regex seguro
const regexSeguro = /^[a-zA-Z0-9.-]+$/;
return regexSeguro.test(entrada);
}
3. Configurar limites de tempo de execução (Timeouts)
Sempre que a sua linguagem de programação oferecer suporte (como .NET ou PHP), defina um timeout curto para a execução do regex. Por exemplo, configure um limite de 100 milissegundos; caso o tempo expire, aborte o processo e trate a exceção para evitar a exaustão da CPU.
Auditoria de Segurança e Ferramentas
A identificação de vulnerabilidades ReDoS deve fazer parte do Ciclo de Vida de Desenvolvimento Seguro (SDLC). Do mesmo modo que realizamos uma auditoria de vulnerabilidades comparando IA vs pentesting humano para mapear riscos da infraestrutura corporativa, devemos utilizar linters para verificar a solidez dos padrões regex.
Enquanto falhas severas na esteira de desenvolvimento — como a recente vulnerabilidade de execução de código no Cursor IDE causada por Git malicioso — requerem investigações dinâmicas e testes de invasão detalhados, problemas de regex são fáceis de mitigar estaticamente.
Para testar seus padrões interativamente e com total segurança, utilize o nosso Testador de Regex online, garantindo que suas expressões não fiquem presas em loops catastróficos.
Conclusão
Criar um regex seguro exige atenção a como os caracteres são computados sob o capô. Negligenciar o risco ReDoS facilita que atacantes externos derrubem seus servidores com requisições simples contendo apenas algumas dezenas de caracteres.
Garantir o compartilhamento de melhores práticas de segurança na equipe é fundamental; recomendamos a leitura do nosso guia sobre como compartilhar senhas de forma segura na internet para elevar a proteção das informações confidenciais do seu time. Controle o tamanho das entradas de dados, simplifique seus regex e mantenha o monitoramento constante dos seus ambientes de produção.
Fontes e Referências recomendadas:
- OWASP: Regular Expression Denial of Service - ReDoS — Guia técnico da fundação OWASP sobre mitigação de ataques ReDoS.
- Google RE2 Engine Documentation — Especificações técnicas do motor linear RE2 desenvolvido pelo Google.
- Artigo relacionado na TecnoCrypter: Auditoria de Vulnerabilidades: IA vs Pentesting Humano.


