flawopen.com/ReDoS/JavaScript RegExp
¿JavaScript RegExp es vulnerable a ReDoS?
Imagina a un empleado que prueba todas las formas de dividir una pila de formularios cuando falta la marca final: un patrón ambiguo puede obligar al motor regex a revisar muchos caracteres una y otra vez. La ruta habitual de RegExp en V8 puede retroceder así; limitar la entrada y usar un patrón de coste predecible acota el trabajo. En Node, la coincidencia síncrona se ejecuta en el hilo del event loop y retrasa otros callbacks del proceso. V8 documenta un motor experimental sin backtracking, activado mediante flags y con limitaciones de patrones; no des por hecho que esté habilitado en producción.
// Repetición anidada ambigua sobre datos de la solicitud
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);
});
// Limita la entrada y acepta solo la gramática del campo
app.post('/search', (req, res) => {
const q = req.body.q;
if (typeof q !== 'string' || q.length > 128)
return res.sendStatus(400);
// Gramática de ejemplo: caracteres ASCII de palabra y espacios
if (!/^[\w ]{1,128}$/.test(q))
return res.sendStatus(400);
res.sendStatus(200);
});
Por qué Node.js amplifica el impacto de ReDoS
La coincidencia síncrona de una expresión regular se ejecuta en el hilo JavaScript que atiende callbacks en un proceso Node.js. Si el patrón tarda con una entrada casi coincidente o fallida, ese event loop no puede ejecutar otros callbacks ni avanzar solicitudes hasta que termine. Los workers, varios procesos o réplicas pueden conservar parte de la capacidad, pero cada proceso afectado aún puede quedar bloqueado.
El impacto depende de la alcanzabilidad, complejidad del patrón, límites de entrada y topología. El atacante debe alcanzar la coincidencia vulnerable con una entrada que active su ruta costosa. Trátalo como riesgo de disponibilidad para el proceso afectado; que caiga todo el servicio depende de workers, réplicas, enrutamiento y comprobaciones de salud.
Caso real en npm: CVE-2026-83606 en xmldom
El aviso revisado de @xmldom/xmldom registra CWE-1333 en el análisis de instrucciones de procesamiento: la gramática vulnerable permite que un grupo codicioso de espacios y otro perezoso de datos consuman los mismos espacios. Si falta el cierre ?>, el parser prueba muchas particiones y tarda tiempo cuadrático. Afecta a las versiones 0.9.0-beta.9 a 0.9.10; 0.9.11 lo corrige impidiendo que el separador devuelva espacios al grupo de datos. El aviso limita el problema a la ruta 0.9.x del paquete con ámbito; no señala como afectados 0.8.x ni el paquete sin ámbito.
La auditoría de dependencias ayuda, pero no demuestra que las regex sean seguras
npm audit informa de avisos conocidos asociados a dependencias del árbol del proyecto; no analiza todas las regex del código ni descubre fallos ReDoS sin publicar. Mantén actualizadas las dependencias directas y transitivas, revisa las rutas afectadas e inspecciona aparte los patrones que procesan texto controlado por usuarios.
npm audit --omit=dev
La auditoría cubre avisos conocidos, no todos los riesgos regex. Revisa el informe según tu despliegue y evalúa por separado si una entrada no confiable puede llegar a una coincidencia costosa y si su tamaño está limitado.
Preguntas frecuentes
La API RegExp no ofrece un timeout por coincidencia. Prefiere patrones simples y limita la entrada antes de comparar. Si necesitas una coincidencia compleja, aísla el trabajo en un worker o proceso hijo con un plazo de terminación efectivo; esto limita el impacto, pero no vuelve eficiente el patrón.
Sí. Una coincidencia síncrona patológica puede congelar el hilo principal de la página hasta que termine y bloquear la interfaz. Limita la entrada, simplifica el patrón y evita ejecutarlo con cada tecla.
Trata los patrones del usuario como entrada ejecutable para un motor potencialmente costoso. No aceptes patrones arbitrarios en un servidor sin límites estrictos y aislamiento. Si solo se necesita búsqueda literal, escapa la entrada como literal regex o usa APIs de búsqueda de texto; escapar evita cambios sintácticos, pero no sustituye el límite de tamaño.
Referencias y correcciones
- Aviso de GitHub — CVE-2026-83606 en @xmldom/xmldom
- xmldom — notas de la versión 0.9.11
- Node.js — no bloquees el event loop (ReDoS)
- V8 — motor RegExp sin backtracking y limitaciones
- npm — auditoría de dependencias
- CWE-1333 — complejidad ineficiente de expresiones regulares