Ciberseguridad

CVE-2026-40897: Ejecución Arbitraria de JavaScript en Math.js

Team Nippysoft
19 min de lectura
CVE-2026-40897: Ejecución Arbitraria de JavaScript en Math.js

Cuando una biblioteca matemática utilizada por millones de desarrolladores para realizar evaluación controlada de expresiones se convierte en un vector de ejecución de código arbitrario en el servidor, las consecuencias van mucho más allá de una actualización de dependencia. CVE-2026-40897, publicado el 24 de abril de 2026, documenta exactamente este escenario en Math.js, una de las bibliotecas matemáticas más utilizadas en el ecosistema de JavaScript y Node.js. La Base de Datos Nacional de Vulnerabilidades le asigna una puntuación CVSS de 8.8 ALTO, con un vector que refleja baja complejidad de ataque, accesibilidad por red e impacto total sobre confidencialidad, integridad y disponibilidad. El aviso de seguridad GHSA-29qv-4j9f-fjw5 es explícito: no existe ninguna solución alternativa y actualizar a la versión 15.2.0 es la única remediación disponible.

El rango vulnerable abarca Math.js desde la versión 13.1.1 hasta 15.1.x inclusive. Cualquier aplicación que exponga el parser de expresiones a entrada controlada por el usuario y ejecute alguna versión dentro de este rango tiene un riesgo activo de ejecución remota de código. El parser de expresiones no es una funcionalidad periférica de la biblioteca; es central en Math.js y se utiliza ampliamente en sistemas de producción de educación, analítica, ingeniería y finanzas. Su escala de adopción convierte esta falla en un problema de cadena de suministro de software tanto como una vulnerabilidad puntual.

Este análisis cubre el mecanismo técnico de la falla, el vector CVSS completo, escenarios de ataque concretos sobre arquitecturas reales, el error arquitectónico más común que amplifica la exposición y los controles que deben acompañar la actualización de versión como parte de una respuesta completa.

Math.js y la Superficie de Ataque del Parser de Expresiones

Math.js se ha consolidado como la dependencia estándar para computación numérica en aplicaciones JavaScript. Ofrece matemáticas simbólicas, operaciones con matrices, números complejos, manejo de unidades físicas y un parser de expresiones capaz de evaluar expresiones matemáticas proporcionadas como cadenas de texto en tiempo de ejecución. Esta combinación lo convierte en la opción preferida para herramientas de computación científica, plataformas educativas, dashboards de analítica, sistemas de modelado financiero y constructores de aplicaciones sin código. La biblioteca se descarga millones de veces al mes desde npm y aparece como dependencia directa o transitiva en una franja amplia del ecosistema JavaScript de producción.

Qué Hace el Parser de Expresiones

El parser de expresiones acepta una cadena de texto como 2 * x + sin(pi) y la evalúa contra un objeto de scope configurable que el desarrollador proporciona. Las aplicaciones usan esta capacidad para ofrecer evaluación de fórmulas genuinamente dinámica: los usuarios pueden escribir sus propios cálculos sin que el desarrollador deba anticipar cada expresión posible de antemano.

Los casos de uso de producción que comúnmente enrutan entrada del usuario hacia el parser de expresiones incluyen:

  • Calculadoras científicas en línea y entornos interactivos de tutoría matemática
  • Dashboards de analítica donde los usuarios definen métricas personalizadas con fórmulas
  • Herramientas de simulación de ingeniería que aceptan expresiones matemáticas parametrizadas
  • Plataformas no-code y low-code con evaluación de fórmulas estilo hoja de cálculo
  • Herramientas de modelado financiero donde los usuarios configuran sus propios KPIs
  • APIs de backend que procesan filtros o reglas de transformación basados en expresiones

En todos estos escenarios el patrón es idéntico: entrada controlada por el usuario fluye hacia math.evaluate(), math.compile() u otra API relacionada. Esa es la superficie de ataque exacta que explota CVE-2026-40897; no es un caso extremo sino el caso de uso principal documentado de esta característica.

Arquitectura del Parser y el Límite de Confianza

Internamente, el parser convierte la cadena de entrada en un Árbol de Sintaxis Abstracta (AST) y lo recorre para producir un resultado. Entre las operaciones que procesa se encuentran asignaciones de propiedades, llamadas a funciones, operaciones de índice e interacciones con objetos tipados como matrices y unidades físicas. Para operar de forma segura con entrada no confiable, toda operación que pueda interactuar con el modelo de objetos de JavaScript debe estar restringida a los objetos que la biblioteca controla explícitamente. Entre las versiones 13.1.1 y 15.1.x, esta restricción era incompleta para una clase específica de operaciones de escritura de propiedades: esa es la raíz de CVE-2026-40897.

Análisis Técnico de CVE-2026-40897

La vulnerabilidad se clasifica bajo CWE-915: Modificación Controlada de Forma Inapropiada de Atributos de Objetos Determinados Dinámicamente. Esta categoría describe casos donde una aplicación permite que la entrada externa determine tanto qué objeto objetivo como qué atributo modificar, sin restringir adecuadamente el conjunto de objetos alcanzables. El patrón es conocido en ataques de prototype pollution, pero se aplica igualmente a cualquier sistema de evaluación de expresiones que admita escrituras dinámicas de propiedades sin el control de scope adecuado.

Mecanismo de la Falla

El lenguaje de expresiones de Math.js soporta sintaxis de asignación. Cuando el parser procesa una expresión que establece una propiedad en un objeto, debe resolver el objeto objetivo y aplicar la escritura. En un evaluador correctamente aislado, esta resolución se limitaría a los objetos que el desarrollador introdujo explícitamente en el scope de evaluación. La falla presente entre las versiones 13.1.1 y 15.1.x permitía a un atacante construir una expresión que, durante la evaluación, activara un setter de propiedad en un objeto JavaScript fuera del límite de scope previsto.

Dado que el setter se ejecuta como código JavaScript estándar, cualquier lógica adjunta a él se ejecuta con los mismos privilegios que el contexto de evaluación de Math.js. En un entorno de servidor Node.js, el código del atacante se ejecuta en el servidor con acceso total al proceso: variables de entorno, sistema de archivos, pila de red y credenciales en memoria. Este es un escenario de ejecución remota de código completo sin ningún mecanismo que limite el impacto una vez que el setter es activado.

El parche en la versión 15.2.0 (commit 513ab2a0e01004af91b31aada68fae8a821326ad, PR #3656) ajusta la lógica interna de resolución de escritura de propiedades. Tras la corrección, solo los objetos explícitamente introducidos en el scope de evaluación pueden tener sus atributos modificados mediante operaciones de asignación de expresiones.

Escenario práctico: Un atacante con una cuenta básica de usuario envía una expresión diseñada para activar un setter en un objeto JavaScript interno a través del parser. El servidor evalúa esta expresión durante el procesamiento normal de la solicitud. El código del atacante se ejecuta de inmediato con privilegios completos del proceso; sin pasos adicionales, sin interacción de otros usuarios, sin necesidad de acceso administrativo.

Análisis del Vector CVSS 8.8

El vector completo CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H se alinea con precisión al mecanismo descrito:

  • AV:N (Vector de Ataque: Red): La expresión maliciosa llega al servidor como parte de una solicitud HTTP estándar. No se requiere presencia física ni posición adyacente en la red.
  • AC:L (Complejidad de Ataque: Baja): No se necesitan condiciones de carrera, configuraciones especiales ni estados previos. Una cadena de expresión correctamente formada es el único requisito.
  • PR:L (Privilegios Requeridos: Bajos): La mayoría de las aplicaciones que exponen evaluación de fórmulas requieren una cuenta de usuario, pero no acceso administrativo. Una sesión autenticada básica es suficiente.
  • UI:N (Interacción de Usuario: Ninguna): La vulnerabilidad se activa cuando el servidor procesa la expresión. No se requiere acción de ningún otro usuario.
  • C:H / I:H / A:H: La ejecución de código en el servidor significa pérdida completa en las tres dimensiones de seguridad simultáneamente.

La puntuación EPSS de 0.051% (percentil 16) refleja la ausencia de explotación activa generalizada en el momento de la divulgación. Sin embargo, la baja complejidad de ataque combinada con la accesibilidad por red crea una brecha corta entre investigación y exploit armado.

CVE-2026-40897 — Flujo de Ataque: Parser de Expresiones Math.jsAtacanteExpresion MathMaliciosaMath.jsParser deExpresiones / ASTCWE-915Setter de PropiedadInseguroFuera de ScopeJS ArbitrarioEjecucion (RCE)Codigo en ServidorServidor ComprometidoC:H | I:H | A:HCVSS 8.8 ALTOAcceso Total al ProcesoVulnerable: mathjs >= 13.1.1 y < 15.2.0 | Corregido: mathjs 15.2.0 | Commit: 513ab2a | PR #3656CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H | EPSS: 0.051% | GHSA-29qv-4j9f-fjw5

Escenarios de Ataque en Produccion

La vulnerabilidad adquiere mayor claridad cuando se mapea sobre las arquitecturas donde Math.js aparece con frecuencia en produccion. Tres escenarios ilustran el alcance real de la superficie de ataque.

Plataforma Educativa con Evaluador de Expresiones en Vivo

Una plataforma de tutorias matematicas en linea permite a estudiantes registrados enviar expresiones a una calculadora integrada en el navegador. El backend en Node.js recibe la expresion como parametro y la pasa directamente a math.evaluate() en un servidor con Math.js 14.x. La plataforma considera que el registro de cuenta es un control de acceso suficiente. Bajo CVE-2026-40897, cualquier estudiante con una cuenta valida puede enviar una expresion que ejecute JavaScript arbitrario en el servidor de la aplicacion. El atacante obtiene acceso inmediato a los tokens de sesion de usuarios activos, las credenciales de base de datos almacenadas en el entorno del proceso y las claves de API cargadas como variables de entorno. El requisito de autenticacion no ofrece ninguna proteccion frente a esta clase de ataque; solo satisface PR:L, el nivel minimo de privilegio requerido.

Dashboard de Analitica con Metricas Calculadas por el Usuario

Las plataformas de analitica frecuentemente permiten a los usuarios escribir formulas de metricas personalizadas. Si Math.js es el motor de evaluacion en el servidor y ejecuta una version dentro del rango vulnerable, el editor de formulas se convierte en una interfaz de ejecucion de codigo arbitrario para cualquier usuario autenticado. La gravedad en este escenario se amplifica porque las plataformas de analitica tipicamente mantienen integraciones activas con data warehouses, almacenamiento en la nube, APIs de terceros y servicios internos: todos accesibles una vez que el codigo se ejecuta en el servidor comprometido.

API de Backend que Acepta Parametros de Expresion

Algunos servicios de backend exponen parametros basados en expresiones para computacion dinamica. Si las expresiones de los llamadores de la API llegan a Math.js sin que la aplicacion ejecute la version 15.2.0, cada llamador con un token valido es un atacante potencial. En arquitecturas de microservicios el impacto se propaga: el codigo ejecutado dentro de un servicio comprometido puede alcanzar otros servicios internos que confian en el componente comprometido, habilitando movimiento lateral a traves de la infraestructura.

El denominador comun en los tres escenarios es identico: entrada controlada por el usuario llega al parser de expresiones de Math.js en un servidor Node.js con una version vulnerable. La correccion es la misma independientemente del dominio o escala de la aplicacion.

Versiones Afectadas y Estado del Parche

CVE-2026-40897 fue introducido en Math.js version 13.1.1 y esta presente hasta la version 15.1.x inclusive. La version 15.2.0, publicada el 24 de abril de 2026, contiene la correccion completa. No existe ninguna mitigacion parcial, ningun indicador de configuracion para deshabilitar el comportamiento vulnerable y ninguna solucion alternativa disponible dentro del rango afectado.

Rango de VersionEstadoAccion Recomendada
Inferior a 13.1.1No afectado por CVE-2026-40897Actualizar por otras mejoras de seguridad
13.1.1 hasta 15.1.xVULNERABLE — CVSS 8.8 ALTOActualizar a 15.2.0 de inmediato. No existe solucion alternativa.
15.2.0 en adelanteCorregidoSeguro. Continuar monitoreando las notas de version.

Insight tecnico: Las dependencias transitivas requieren atencion especial. Ejecutar npm list mathjs --all revela cada instancia de la biblioteca en todos los niveles del arbol de dependencias, incluidas las instancias anidadas invisibles en el package.json de nivel superior.

El Error Arquitectonico que Maximiza la Exposicion

El error mas frecuente al integrar el parser de expresiones de Math.js es tratar la autenticacion como un limite de seguridad suficiente para la evaluacion de expresiones. La metrica CVSS PR:L responde directamente a esto: bajos privilegios son todo lo que el ataque requiere. Exigir inicio de sesion no protege el evaluador del lado del servidor frente a un usuario malicioso que tiene una cuenta valida.

Un error estrechamente relacionado es llamar a math.evaluate() con un scope excesivamente amplio o sin un scope definido explicitamente. Incluso despues de actualizar a la version parcheada, exponer la biblioteca completa de funciones de Math.js a expresiones controladas por el usuario es una practica deficiente. La superficie de ataque de cualquier evaluador de expresiones escala directamente con la amplitud del scope en el que opera.

Los equipos a veces asumen que el uso prolongado sin incidentes reportados implica seguridad. CVE-2026-40897 fue introducido en la version 13.1.1 y puede haber estado presente en despliegues de produccion durante un periodo extendido antes de la divulgacion. La ausencia de incidentes reportados no es evidencia de ausencia de explotacion.

Remediacion y Endurecimiento Arquitectonico

La correccion inmediata es directa. El endurecimiento arquitectonico que debe acompañarla requiere decisiones de diseño deliberadas que trasciendan esta vulnerabilidad especifica.

Actualizar a mathjs 15.2.0

# npm
npm install mathjs@15.2.0

# yarn
yarn add mathjs@15.2.0

# pnpm
pnpm add mathjs@15.2.0

Auditar y Fortalecer los Puntos de Llamada

  1. Buscar en todo el codigo fuente cada invocacion de math.evaluate(), math.compile() y math.parse(), incluyendo funciones wrapper y capas de servicio.
  2. Para cada punto de llamada, rastrear el origen de la entrada: si alguna parte puede ser influenciada por un usuario, debe tratarse como no confiable.
  3. Pasar un objeto de scope minimo y explicitamente construido a math.evaluate(). Incluir solo lo que el caso de uso especifico requiere.
  4. Para contextos de alto riesgo, usar math.parse() para construir el AST e inspeccionar los tipos de nodo antes de llamar a evaluate(). Rechazar expresiones que referencien funciones u operadores que la aplicacion no necesita.

Combinar la restriccion de scope con la inspeccion del AST crea dos barreras independientes entre la entrada del usuario y el motor de evaluacion. Si alguna de las dos es eludida por una vulnerabilidad futura, la otra permanece activa.

Consideraciones de Rendimiento y Escalabilidad

La evaluacion de expresiones tiene una sobrecarga computacional no trivial cuando se invoca por cada solicitud. La optimizacion estandar para servicios de alto rendimiento es usar math.compile() para precompilar expresiones en objetos de funcion reutilizables y almacenarlos en cache indexados por la cadena de expresion. Esto evita repetir la construccion del AST y el procesamiento en tiempo de analisis para expresiones recurrentes entre solicitudes.

El paso de inspeccion del AST recomendado como control de defensa en profundidad añade una sobrecarga minima, bien por debajo de un milisegundo para expresiones de longitud practica. Para servicios donde la evaluacion de expresiones es un cuello de botella de rendimiento, moverla fuera de la ruta sincrona de solicitudes hacia un hilo de trabajo o un microservicio de evaluacion dedicado es una decision arquitectonica solida. Aisla el contexto de evaluacion del proceso principal de la aplicacion, limita el radio de explosion de cualquier vulnerabilidad futura en esta capa y permite el escalado independiente del nivel de computacion.

Preguntas Frecuentes

¿Esta vulnerabilidad afecta el uso de Math.js unicamente en el navegador?

El riesgo critico es el despliegue del lado del servidor en Node.js. Cuando Math.js se ejecuta exclusivamente en el navegador y no ocurre evaluacion en el servidor, un atacante que explote esta vulnerabilidad ejecuta codigo en su propia sesion de navegador, no en infraestructura compartida. Esto no cruza los limites de otros usuarios y no tiene las mismas consecuencias de ejecucion remota de codigo. Aun asi, se recomienda actualizar como practica estandar de seguridad.

¿Existe alguna mitigacion parcial sin necesidad de actualizar?

El aviso de seguridad de GitHub indica explicitamente que no existe solucion alternativa y que actualizar a 15.2.0 es obligatorio. La validacion de entrada a nivel de aplicacion puede reducir la superficie de ataque rechazando algunas expresiones maliciosas antes de que lleguen al parser, pero no puede prevenir de forma confiable la explotacion de una falla que opera al nivel de resolucion interna de escritura de propiedades del parser. Tratar la validacion como medida temporal junto con un proceso de actualizacion expedito, no como sustituto de la misma.

¿Como verifico la version instalada en todos los niveles de dependencias?

Ejecutar npm list mathjs --all en el directorio del proyecto. Este comando lista todas las instancias del paquete en cada nivel del arbol de dependencias, incluyendo las anidadas incorporadas transitivamente. Si alguna instancia muestra una version entre 13.1.1 y 15.1.x y la aplicacion enruta entrada del usuario al parser de expresiones, el proyecto esta expuesto.

¿La actualizacion a 15.2.0 rompe las expresiones existentes?

El parche apunta a la logica interna de resolucion de escritura de propiedades, no a la sintaxis publica de expresiones. Las aplicaciones que no dependen del comportamiento especifico que explota la vulnerabilidad deben continuar evaluando expresiones correctamente tras la actualizacion. Ejecutar la suite de pruebas existente contra 15.2.0 en un entorno de staging antes de desplegar a produccion es el paso de verificacion estandar.

Conclusion

CVE-2026-40897 es un recordatorio directo de que los motores de evaluacion de expresiones requieren tanto un diseño cuidadoso de la biblioteca como practicas de integracion disciplinadas. Math.js es una biblioteca bien mantenida con una comunidad activa, y la divulgacion rapida a traves de GHSA-29qv-4j9f-fjw5, el PR publico #3656 y el commit de correccion disponible reflejan un proceso de respuesta de seguridad en el que el ecosistema puede confiar.

La respuesta de cualquier equipo afectado es de dos partes: actualizar a 15.2.0 sin demora y auditar cada punto de llamada donde el parser de expresiones recibe entrada que un usuario puede influenciar. La actualizacion cierra la vulnerabilidad conocida. La auditoria evita que la arquitectura circundante cree condiciones para que la siguiente emerja.

Verificar la version instalada en cada entorno, llevar la actualizacion al pipeline de despliegue en el plazo mas corto disponible y tratar la restriccion de scope y la validacion de entrada como controles no negociables para cualquier aplicacion que evalue expresiones matematicas proporcionadas por el usuario. Cada hora que la version vulnerable permanece en produccion es exposicion innecesaria a un riesgo de ejecucion remota de codigo CVSS 8.8.

Referencias

Suscríbete

Recibe los últimos artículos directamente en tu bandeja de entrada.

Este sitio está protegido por reCAPTCHA. Aplican la Política de Privacidad y los Términos de Servicio de Google.

Comentarios

Aún no hay comentarios. ¡Sé el primero en compartir tu opinión!

¡Suscrito!

¡Registrado! Hemos enviado un enlace de confirmación a tu correo electrónico. Si no lo ves, revisa tu carpeta de spam.

Error

Ocurrió un error. Por favor intenta de nuevo.