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

ReDoS no Node.js: proteja regex contra ataques

Atualizado em: 8 de outubro de 2026

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

ReDoS, ou Regular Expression Denial of Service, acontece quando uma expressão regular possui caminhos de backtracking excessivos e recebe uma entrada criada para consumir CPU. Como o JavaScript executa regex na thread principal, uma única validação pode bloquear o event loop e atrasar todas as requisições do processo Node.js.

Exemplo perigoso

const pattern = /^(a+)+$/;

pattern.test('aaaaaaaaaaaaaaaaaaaaaaaaaaaa!');

Grupos repetidos e sobrepostos podem causar crescimento exponencial do trabalho para uma entrada que quase corresponde.

Por que bloqueia o Node.js

O motor de regex executa de forma síncrona. Enquanto ele tenta combinações, timers, respostas HTTP e callbacks não avançam. CPU sobe e event loop delay aumenta.

Padrões de risco

  • quantificadores aninhados, como (a+)+;
  • alternativas sobrepostas, como (a|aa)+;
  • repetição ampla antes de um sufixo;
  • grupos opcionais repetidos;
  • backtracking em strings sem limite;
  • regex construída pelo usuário.

Limite a entrada

if (typeof value !== 'string' || value.length > 256) {
  throw new ValidationError('Valor inválido');
}

Limites reduzem impacto, mas não corrigem uma expressão exponencial. Use as duas medidas.

Prefira validação simples

Para campos estruturados, combine verificações:

function isSafeUsername(value) {
  if (typeof value !== 'string') return false;
  if (value.length < 3 || value.length > 30) return false;
  return /^[a-zA-Z0-9_]+$/.test(value);
}

Uma regex ancorada e com classe simples é mais previsível.

Email

Não tente implementar toda a especificação de email com uma expressão gigante. Use validação pragmática, limite de tamanho e confirmação por envio de mensagem.

URLs

Use o parser nativo:

function parseHttpsUrl(value) {
  const url = new URL(value);
  if (url.protocol !== 'https:') throw new ValidationError();
  return url;
}

Regex não substitui parsing e validação de segurança contra SSRF.

Escape de entrada

Quando o usuário fornece um termo literal para busca por regex, escape metacaracteres:

function escapeRegExp(value) {
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

const regex = new RegExp(escapeRegExp(term), 'i');

Ainda limite tamanho e quantidade de buscas.

Não aceite regex arbitrária

Uma API que recebe padrões do usuário permite ReDoS direto. Para filtros, ofereça operadores predefinidos, busca literal, prefixo ou linguagem com limites.

Static analysis

Ferramentas como safe-regex podem sinalizar padrões suspeitos, mas possuem falsos positivos e negativos. Use como camada no CI, não como prova definitiva.

Testes adversariais

const inputs = [
  'a'.repeat(100) + '!',
  'a'.repeat(1000) + '!',
  ' '.repeat(10000),
];

for (const input of inputs) {
  const start = performance.now();
  pattern.test(input);
  const duration = performance.now() - start;
  expect(duration).toBeLessThan(20);
}

Benchmarks em CI compartilhado podem oscilar; use limites amplos ou runner dedicado para regressões importantes.

Timeout não interrompe regex

Um setTimeout não consegue interromper código síncrono que bloqueia o event loop. O callback do timeout só executa depois que a regex termina.

Worker Threads

Quando uma regex complexa é inevitável, execute em worker isolado e termine após prazo:

const worker = new Worker(new URL('./regex-worker.js', import.meta.url), {
  workerData: { pattern, input },
});

const timer = setTimeout(() => worker.terminate(), 100);

Não envie padrões arbitrários sem limites. Criar worker por request também custa recursos; use pool controlado.

RE2

Motores baseados em RE2 evitam backtracking exponencial, mas não suportam todos os recursos de regex JavaScript, como algumas referências e lookarounds. Avalie compatibilidade e dependência nativa.

Regex em dependências

Vulnerabilidades podem existir em routers, validadores, parsers, markdown e bibliotecas de sanitização. Mantenha dependências atualizadas e revise advisories.

JSON Schema pattern

O keyword pattern pode executar regex sobre entrada externa. Use expressões simples, maxLength e testes de pior caso.

Rotas Express

Parâmetros e rotas podem usar padrões. Não crie uma rota com regex ambígua para caminhos de tamanho ilimitado. Configure limite de URL no proxy.

Logs e busca

Sistemas que permitem filtros regex em logs precisam de sandbox, timeout real no motor ou linguagem limitada. Não execute padrão enviado pelo painel diretamente no processo da API.

Rate limiting

Rate limiting reduz volume, mas uma única entrada pode bloquear o processo. Corrija a expressão e limite tamanho.

Event Loop Utilization

Monitore ELU e event loop delay. Um pico de CPU com poucas requisições pode indicar regex, parsing, compressão ou outro trabalho síncrono.

Profiling

Use --prof, flamegraphs ou Clinic.js. A pilha pode mostrar funções de RegExp ou validação próximas do gargalo.

Resposta e proteção

Rejeite entrada grande antes da regex. Configure limites de body, URL, headers e campos. Não devolva a expressão interna em erros.

Fuzzing

Gere strings longas, quase correspondentes e repetitivas. Fuzzing é especialmente útil para parsers e regras de validação adicionadas por usuários internos.

Revisão de código

Para cada regex nova, pergunte:

  • qual é o tamanho máximo da entrada?
  • há quantificadores aninhados?
  • alternativas se sobrepõem?
  • um parser seria melhor?
  • o padrão vem do usuário?
  • há teste de pior caso?

Erros comuns

  • regex complexa para email;
  • sem limite de entrada;
  • aceitar padrão do usuário;
  • achar que setTimeout interrompe;
  • confiar somente em scanner;
  • ignorar patterns de schemas;
  • usar rate limit como correção;
  • não medir event loop;
  • regex em dependência desatualizada.

Fluxo recomendado

  1. limite tamanho;
  2. simplifique o padrão;
  3. prefira parsers;
  4. escape busca literal;
  5. proíba regex arbitrária;
  6. analise no CI;
  7. teste entradas adversariais;
  8. monitore event loop;
  9. isole casos complexos;
  10. atualize dependências.

Combine a proteção com JSON Schema, Event Loop Utilization, CPU Profiling, Worker Threads e Rate Limiting.

Consulte a referência da OWASP sobre ReDoS e a documentação de expressões regulares da MDN.

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