Saltar al contenido principal
eLearner.app
Módulo 8 · Lección 4 de 432/32 en el curso~14 min
Lecciones del módulo (4/4)

Escribir patrones ReDoS-safe

ReDoS (Denegación de Servicio mediante Expresiones Regulares) es una clase de ataque donde un input cuidadosamente diseñado hace que el tiempo de coincidencia de una regex explote. El motor de JS utiliza backtracking: si un patrón es "ambiguo", ante una entrada desafortunada puede realizar un número exponencial de intentos.

El clásico patrón catastrófico

Code
Pattern: ^(a+)+$
Input:   "aaaaaaaaaaaaaaaaaaaaab"

Para encontrar coincidencia, el motor prueba cada partición posible de "a" entre los dos cuantificadores +. En 20 "a"s eso es 2^20 = ~1 millón de intentos. En 30 "a"s, mil millones.

Otros ejemplos peligrosos:

  • (a*)*b -- "estrellas anidadas".
  • (a|a)* -- alternativas superpuestas.
  • (\w+)+@ -- grupos codiciosos con un cuantificador externo.

Cómo detectar el peligro

Busca estas estructuras:

  1. Cuantificador dentro de un cuantificador: (...+)+, (...*)*, (...{n,})+.
  2. Alternativas superpuestas bajo un cuantificador: (a|ab)*, (\w|\d)+.
  3. Lookahead/lookbehind con alternativas complejas repetidas.

Reescritura defensiva

Code
Dangerous:  ^(\w+\s+)+$
Safe:       ^(?:\w+\s+)*\w+$

La versión segura separa el caso base del caso repetido, eliminando la ambigüedad. Otras técnicas:

  • Cuantificadores posesivos (a++) -- no admitidos en JS, pero disponibles en otros motores.
  • Patrones atómicos ((?>...)) -- no en JS.
  • Limitar la longitud del input antes de compararlo.
  • Timeout en la coincidencia (el editor de este curso utiliza un worker con un tiempo de espera de 500 ms).

Recomendaciones para patrones seguros frente a ReDoS

  1. Asegúrate de que las opciones en una alternancia sean mutuamente excluyentes (ej. no uses (a|a+)).
  2. Evita aplicar cuantificadores anidados a expresiones superpuestas (ej. (\\s*)*).
  3. Prefiere siempre clases de caracteres negadas específicas ([^\\n]*) sobre el punto comodín genérico (.*).

Pruébalo tú

Ejercicio#regex.m8.l4.e1
Intentos: 0Cargando...

Identifica patrones de letras repetidas, pero de una manera segura frente a ReDoS. Usa una sola clase de caracteres, NO grupos anidados como (a+)+.

Cargando editor...
Mostrar pista

Reemplaza el peligroso (a+)+ con un simple a+. El resultado es el mismo, pero seguro.

Solución disponible después de 3 intentos

Ejercicio de repaso

Ejercicio#regex.m8.l4.e2
Intentos: 0Cargando...

Reconoce una secuencia de palabras separadas por espacios, de forma segura frente a ReDoS. Usa la estructura `(?:word+spaces+)*word` en lugar de `(word+space+)+`.

Cargando editor...
Mostrar pista

Reemplaza el grupo de captura (\w+\s+)+ con la versión disjunta (?:\w+\s+)*\w+.

Solución disponible después de 3 intentos

Desafío adicional

Ejercicio#regex.m8.l4.e3
Intentos: 0Cargando...

Haz seguro el patrón vulnerable `(\w+\s*)+:` que causa ReDoS, eliminando la recursividad de espacios superpuestos.

Cargando editor...
Mostrar pista

Mueve el espacio para que no se superponga con la repetición del grupo: (?:\w+\s+)*\w+:

Solución disponible después de 3 intentos