FlawOpen

flawopen.com/ReDoS/JavaScript RegExp

JavaScript RegExp é vulnerável a ReDoS?

CWE-1333: Inefficient Regular Expression ComplexityPágina de referência
Resposta curta

Imagine um atendente tentando todas as formas de dividir uma pilha de formulários quando falta a marca final: um padrão ambíguo pode obrigar o mecanismo regex a revisitar os mesmos caracteres muitas vezes. O caminho usual de RegExp do V8 pode fazer esse backtracking; limitar a entrada e usar um padrão de custo previsível restringe o trabalho. No Node, a correspondência síncrona executa na thread do event loop e atrasa outros callbacks do processo. A V8 documenta um mecanismo experimental sem backtracking, ativado por flags e com limitações de padrões; não presuma que ele esteja habilitado em produção.

VULNERÁVEL
// Repetição aninhada ambígua em dados da requisição
const re = /^(\w+\s?)*$/;

app.post('/search', (req, res) => {
  const q = req.body.q;
  if (!re.test(q)) return res.sendStatus(400);
  res.sendStatus(200);
});
CORRIGIDO
// Limite a entrada e aceite apenas a gramática do campo
app.post('/search', (req, res) => {
  const q = req.body.q;
  if (typeof q !== 'string' || q.length > 128)
    return res.sendStatus(400);

  // Exemplo: somente caracteres ASCII de palavra e espaços
  if (!/^[\w ]{1,128}$/.test(q))
    return res.sendStatus(400);

  res.sendStatus(200);
});

Por que o Node.js amplia o impacto de ReDoS

Uma correspondência regex síncrona roda na thread JavaScript que atende callbacks no processo Node.js. Se o padrão demora em uma entrada quase correspondente ou inválida, o event loop não executa outros callbacks nem avança as requisições até o fim da correspondência. Workers, vários processos ou réplicas podem preservar alguma capacidade, mas cada processo afetado ainda pode travar.

O impacto depende de alcançabilidade, complexidade do padrão, limites de entrada e topologia. O atacante precisa alcançar a correspondência vulnerável com uma entrada que acione o caminho caro. Trate isso como risco de disponibilidade do processo afetado; a indisponibilidade do serviço inteiro depende de workers, réplicas, roteamento e verificações de saúde.

Caso real no npm: CVE-2026-83606 no xmldom

O aviso revisado sobre @xmldom/xmldom registra CWE-1333 no parser de instruções de processamento: a gramática vulnerável permite que um grupo guloso de espaços e um grupo preguiçoso de dados consumam os mesmos espaços. Sem o fechamento ?>, o parser tenta muitas partições e leva tempo quadrático. As versões 0.9.0-beta.9 até 0.9.10 são afetadas; 0.9.11 corrige o problema impedindo que o separador devolva espaços ao grupo de dados. O aviso restringe o problema ao caminho 0.9.x do pacote com escopo; não aponta as linhas 0.8.x ou o pacote sem escopo como afetados.

Auditoria de dependências ajuda, mas não prova segurança das regex

npm audit relata avisos conhecidos associados às dependências da árvore do projeto; não analisa todas as regex do código nem descobre falhas ReDoS ainda não publicadas. Mantenha dependências diretas e transitivas corrigidas, revise os caminhos afetados e inspecione separadamente padrões que recebem texto controlado por usuários.

npm audit --omit=dev

O audit cobre avisos conhecidos, não todos os riscos de regex. Revise o relatório conforme sua implantação e avalie separadamente se a entrada não confiável pode alcançar uma correspondência custosa e se seu tamanho tem limite.

Perguntas frequentes

Posso definir um timeout para uma regex JavaScript?

A API RegExp não oferece timeout por correspondência. Prefira padrões simples e limite a entrada antes de comparar. Se a lógica complexa for necessária, isole-a em worker ou processo filho com prazo de término aplicável; isso limita o impacto, mas não torna o padrão eficiente.

Isso também afeta JavaScript no navegador?

Sim. Uma correspondência síncrona problemática pode congelar a thread principal da página até terminar, bloqueando a interface. Limite a entrada, simplifique o padrão e evite executá-lo a cada tecla digitada.

É seguro usar new RegExp(userInput) na busca?

Trate padrões fornecidos pelo usuário como entrada executável para um mecanismo potencialmente caro. Não aceite padrões arbitrários em servidor sem limites estritos e isolamento. Se a busca deve ser literal, escape a entrada como literal regex ou use APIs de busca textual; escapar evita mudanças na sintaxe, mas não substitui um limite de tamanho.

Referências e correções

Veja também O que é ReDoS (backtracking catastrófico)?