Actualización de seguridad de Node.js: ¿su versión sigue recibiendo parches?
El 21 de octubre Node.js publicó parches de seguridad para las líneas de lanzamiento 22, 24 y 26. Qué versiones son seguras, por qué Node.js 18 y 20 no recibirán parche y cómo comprobar qué versión usa su aplicación.
El 21 de octubre Node.js publicó parches de seguridad para las líneas de lanzamiento 22, 24 y 26. Qué versiones son seguras, por qué Node.js 18 y 20 no recibirán parche y cómo comprobar qué versión usa su aplicación.
Los parches los recibieron solo las líneas de lanzamiento que todavía tienen soporte, y las versiones seguras son 22.23.4, 24.22.1 y 26.12.1, o cualquiera posterior dentro de la misma línea. Node.js 18 y 20 ya han llegado al fin de vida, así que esta actualización de seguridad de Node.js no trae parche de seguridad para ellas, y tampoco lo traerá: si su aplicación funciona sobre alguna de las dos, actualizar significa pasar a otra línea de lanzamiento.
El miércoles 21 de octubre el proyecto Node.js publicó lanzamientos de seguridad para las tres líneas que todavía tienen soporte, y ese mismo día PHP publicó parches de emergencia para las vulnerabilidades que recibieron el nombre PHP2Shell, pero se trata de dos sucesos distintos y de una gravedad distinta. El lanzamiento de Node.js se había anunciado de antemano, el proyecto ha valorado sus vulnerabilidades más graves como altas y no como críticas, y el anuncio no menciona ni soluciones alternativas ni ataques en el entorno real. Eso no permite aplazar la actualización, pero sí desplaza el lugar de la atención: esta vez el mayor riesgo no está en el propio lanzamiento, sino en las versiones que no lo recibieron.
Qué corrigió la actualización de seguridad de Node.js de octubre
El anuncio de Node.js enumera diez vulnerabilidades: el proyecto ha valorado cuatro como altas, tres como medias y tres como bajas, pero esta vez no ha publicado puntuaciones CVSS, así que este artículo usa esa misma valoración.
La más grave de ellas es CVE-2026-111497. El proyecto la llama escritura fuera de límites en el decodificador Brotli, que permite la ejecución remota de código (RCE), y la valora como alta. Brotli es un formato de compresión cuyo decodificador va integrado en Node.js, y en las notas del lanzamiento el parche se describe como un cambio en esa biblioteca integrada. El anuncio no dice por qué camino se puede alcanzar la vulnerabilidad, y la descripción que los desarrolladores de Brotli hacen del arreglo habla solo de que un flujo de datos no válido ahora se reconoce antes. Por eso aquí no se nombran funciones concretas: lo único que se puede afirmar con seguridad es que un fallo del decodificador afecta sobre todo a las aplicaciones que descomprimen datos Brotli procedentes de una fuente en la que no pueden confiar.
Otras tres vulnerabilidades afectan a la comprobación de los certificados TLS, y no son un mismo caso. La primera, valorada como alta, afecta solo a las líneas 26 y 24: la hostname verification, esto es, la comprobación de que el nombre del host coincide con el certificado del servidor al que se conecta, se puede eludir si la dirección IP está escrita con dígitos de ancho completo, por ejemplo 127.0.0.1. La segunda, también alta, afecta a las tres líneas: la comprobación se puede eludir si el nombre de host se puede leer de forma no estricta como una dirección IP. La tercera es media y afecta también a las tres líneas: una notación IPv4 no estándar permite que el nombre DNS indicado en el certificado avale una dirección IP. En las notas del lanzamiento los arreglos quedan formulados en pocas palabras: las direcciones IP escritas de forma atípica ahora se rechazan, y por separado se ha corregido una regresión en la normalización de las direcciones IP. En los tres casos se trata del momento en que Node.js actúa como cliente, es decir, cuando él mismo abre una conexión cifrada con otro servidor, y no del momento en que atiende a quienes lo visitan.
La cuarta vulnerabilidad valorada como alta está en la función dns.resolve, que truncaba los nombres en los que hay un carácter nulo. Entre las de valoración media están un fallo en la reutilización de las conexiones HTTP, en el que una respuesta escrita en la conexión antes de que se enviara la petición podía tratarse como la respuesta a esa petición, y un fallo por el cual la caché de aleatoriedad de crypto.randomUUID() y de randomInt() se guardaba en los startup snapshots y en un único archivo ejecutable (single executable application), de modo que cada proceso repetía los mismos valores. Tres vulnerabilidades de valoración baja afectan al tratamiento de archivos ZIP y al modelo de permisos de Node.js.
El fallo de la caché de aleatoriedad conviene entenderlo con precisión, porque en el caso ordinario no afecta a nada. Solo concierne a los proyectos que arrancan desde un startup snapshot que ellos mismos han construido, o que se distribuyen como un único archivo ejecutable (single executable application, SEA), y allí significa que cada proceso iniciado desde el mismo archivo recibía los mismos valores «aleatorios». Si en un proyecto de ese tipo se formaban identificadores o códigos temporales con crypto.randomUUID() o con randomInt(), podían repetirse de un proceso a otro, así que después del parche de seguridad conviene comprobar si alguno de esos valores se usa allí donde tiene que resultar imposible de adivinar.
El lanzamiento actualiza también varias dependencias integradas, según la línea c-ares, OpenSSL, SQLite y Undici, sobre la que se apoya la función fetch integrada. Asimismo se ha actualizado el listado de autoridades de certificación de confianza, el CA store, a causa de un certificado intermedio de eMudhra que ha quedado comprometido, y las conexiones TLS rechazan ahora las cadenas en las que hay claves públicas bloqueadas.
Qué versiones son seguras
Las versiones corregidas son tres, una por cada línea que tiene soporte: 22.23.4, 24.22.1 y 26.12.1. Todo lo que dentro de su línea sea más antiguo está afectado. No las diez vulnerabilidades alcanzan a todas las líneas: la línea 26 tiene las diez, la línea 24 tiene ocho y la línea 22 tiene siete, porque dos fallos de valoración baja existen solo en la línea más reciente y un fallo de TLS no afecta a la línea 22.
Actualizar dentro de la línea de lanzamiento es el paso más pequeño que cabe dar, y por lo general es también el cambio más seguro que se puede hacer en producción. Aun así, también ese paso puede cambiar el comportamiento, y esta vez hay un ejemplo concreto: el arreglo de la comprobación TLS rechaza ahora las direcciones IP escritas de forma atípica. Si alguna aplicación usó en su momento esa escritura en las conexiones con otro servidor, después de la actualización la conexión puede fallar. Es un agujero de seguridad ya corregido, no un fallo nuevo, pero conviene saberlo antes de actualizar, y no después.
La línea de lanzamiento importa más que el número de versión
Hasta Node.js 26 cada versión mayor recorre un mismo ciclo: primero es la versión actual (Current), después las versiones de número par reciben el soporte a largo plazo activo (Active LTS), luego pasan a Maintenance LTS, fase en la que reciben solo correcciones de errores críticos y parches de seguridad, y al final el soporte cesa por completo, mientras que las versiones de número impar, hasta la línea 25, no recibieron soporte a largo plazo. A partir de Node.js 27 el ciclo cambia: según el calendario de lanzamientos, cada línea recibirá soporte a largo plazo y, durante los 30 meses de ese soporte, permanecerá en la fase activa, sin Maintenance LTS. El proyecto escribe por su cuenta que las aplicaciones de producción deben usar solo versiones de soporte a largo plazo activo o de Maintenance LTS.
Para las líneas que están en uso, los cambios de fase más próximos caen en dos fechas. Según el calendario de lanzamientos de Node.js, la línea 24 pasó a Maintenance LTS el 20 de octubre, un día antes del lanzamiento de seguridad, y la línea 26 recibirá el soporte a largo plazo el 28 de octubre. La línea 22 está en Maintenance LTS desde el 21 de octubre de 2025 y llegará al fin de vida el 30 de abril de 2027, mientras que la línea 24 llegará al fin de vida el 30 de abril de 2028.
La consecuencia práctica es sencilla: la pregunta «¿tenemos la versión más reciente?» por sí sola no dice gran cosa, mientras que la pregunta útil es «¿en qué línea de lanzamiento estamos, y hasta qué fecha recibirá parches?». La primera cambia de respuesta cada mes y la segunda una vez cada par de años, y precisamente por eso la segunda resulta fácil de olvidar.
Node.js 18 y 20: no habrá parche
En el anuncio de Node.js hay una frase que esta vez importa más que las diez vulnerabilidades: las versiones cuyo soporte ha terminado quedan siempre afectadas cuando se produce un lanzamiento de seguridad, y para ellas no se publica parche ni ahora ni más adelante, porque una línea que ha llegado al fin de vida ya no recibe ningún lanzamiento.
Según el calendario de lanzamientos, la línea 16 llegó al fin de vida el 11 de septiembre de 2023, la línea 19 el 1 de junio de 2023, la línea 18 el 30 de abril de 2025 y la línea 20 el 30 de abril de 2026. La última de esas fechas es la que más importa: la línea 20 llegó al fin de vida hace poco menos de seis meses, y un proyecto que se inició sobre ella puede seguir funcionando sin ningún problema que se vea. Precisamente eso vuelve engañosa la situación, porque nada en su funcionamiento indica que los parches de seguridad ya no le corresponden.
Para las empresas que no pueden pasar pronto a una línea con soporte, el anuncio de Node.js menciona una posibilidad: el soporte comercial para las versiones posteriores a Maintenance LTS lo ofrecen los socios del OpenJS Ecosystem Sustainability Program. Es un servicio de pago, y es un arreglo temporal, no un sustituto del paso a una línea con soporte.
Cómo comprobar qué Node.js usa su aplicación
La comprobación lleva minutos, pero hay un sitio en el que es fácil hacerla mal: la versión de Node.js que muestra la terminal no siempre es aquella con la que funciona la aplicación.
Hosting con cPanel. La versión en uso la muestra la sección Software → Setup Node.js App, donde cada aplicación tiene su propia fila y la versión se elige de una lista. En la lista están solo las versiones que el proveedor de hosting ha instalado en el servidor. La orden node -v en un hosting de este tipo puede mostrar una versión distinta de ese ajuste, así que mire precisamente la fila que corresponde a la aplicación.
Servidor propio. La orden node -v muestra la versión que aparece primera en la ruta del sistema, pero un gestor de procesos, por ejemplo PM2 o un servicio de systemd, puede arrancar el programa con un ejecutable del todo distinto. La respuesta en la que se puede confiar es la que el propio proceso declara acerca de sí mismo: el valor de process.version, por ejemplo escrito en el registro en el momento del arranque.
Contenedores. En un entorno Docker la versión la determina la container image, no la máquina anfitriona. Una container image construida antes del 21 de octubre no contiene el parche, con independencia de cuántas veces se haya reiniciado el contenedor, así que hay que reconstruir la container image a partir de una base image actualizada.
Si no hay acceso. Entonces la pregunta es para el proveedor de hosting, o para quien desarrolla la aplicación y la mantiene. La formulación que ahorra un intercambio de mensajes: «¿Qué versión de Node.js usa nuestra aplicación? Dentro de su línea de lanzamiento, ¿está al menos en 22.23.4, 24.22.1 o 26.12.1? Si está en una línea que ha llegado al fin de vida, por ejemplo la 18 o la 20, ¿cuándo está previsto el paso?»
Qué hacer hoy
El orden de hoy es el siguiente: primero actualizar Node.js hasta la versión corregida de su propia línea y reiniciar cada proceso que lo usa, después reconstruir todo aquello en lo que el runtime va integrado y, solo después de eso, planificar el paso de los proyectos que funcionan sobre líneas que han llegado al fin de vida.
Primero, actualice dentro de la línea. A 22.23.4, 24.22.1 o 26.12.1, según la línea en la que esté. Cuando la aplicación está en un hosting, lo hace el proveedor, y el trabajo de usted es asegurarse de que la aplicación usa la versión que ya se ha actualizado.
Segundo, reinicie los procesos. Un proceso que ya está en marcha sigue usando el Node.js con el que se inició, y sustituir el archivo en el disco no le afecta. Lo mismo ocurría con PHP2Shell: el paquete se ha sustituido, pero el proceso viejo sigue trabajando con el código viejo.
Tercero, reconstruya aquello en lo que el runtime va integrado. Las container images de Docker hay que reconstruirlas a partir de una base image actualizada. Si distribuye el programa como un único archivo ejecutable (single executable application, SEA), en ese archivo va integrado el propio Node.js, así que actualizar la versión instalada en el sistema no le afecta, y el archivo hay que volver a construirlo con la versión corregida. Lo mismo alcanza a los startup snapshots, a los que afecta el fallo de la caché de aleatoriedad.
Cuarto, si está en la línea 18 o en la 20, planifique el paso. Es un trabajo mayor que la actualización dentro de la línea, así que conviene empezarlo ahora, y el orden está descrito en la sección siguiente.
Cómo pasar de Node.js 18 o 20
El paso entre versiones mayores no es el trabajo de una sola orden, y conviene hacerlo por partes, eligiendo primero el destino. En la mayoría de los casos ese destino es la línea 24, que recibirá parches de seguridad hasta el 30 de abril de 2028; la línea 22 es una elección razonable solo cuando alguna dependencia importante todavía no admite la línea 24, porque el soporte de la línea 22 termina un año antes.
Después hay que encontrar todos los sitios en los que el proyecto fija su propia versión de Node.js, porque casi siempre son varios: el campo engines de package.json, los archivos .nvmrc o .node-version, la base image del Dockerfile, la configuración del entorno de integración continua (CI) y el ajuste del panel de hosting. Si solo se cambia una parte de esos sitios, en los distintos entornos funcionan versiones distintas, y los fallos aparecen allí donde más cuesta encontrarlos.
A continuación el proyecto hay que instalarlo de nuevo en un entorno de pruebas, con la versión nueva, y hay que ejecutar las pruebas. Una atención particular merecen los paquetes que contienen código compilado: se construyen para una versión concreta de Node.js, así que después del paso puede hacer falta reconstruirlos o actualizarlos. Para cada versión mayor, Node.js publica una lista de cambios en la que se marcan aparte los cambios que pueden romper el código ya existente, y conviene leerla antes del paso, no después.
Solo entonces llega el entorno de producción: el cambio de versión, el reinicio de los procesos y la comprobación de que process.version muestra la versión nueva. La versión vieja puede quedar disponible unos días, por si hay que volver atrás, pero no durante más tiempo, porque es precisamente la versión para la que ya no habrá parche de seguridad.
Qué no se actualiza junto con Node.js
Actualizar Node.js repara el propio runtime y las bibliotecas que van integradas en él, pero no todo lo que la aplicación usa, y es precisamente aquí donde con más frecuencia quedan agujeros que nadie ve.
Paquetes instalados por separado. Si el proyecto usa entre sus dependencias el paquete undici de npm, y no el fetch integrado, ese paquete está en la carpeta node_modules del proyecto, y un lanzamiento de Node.js no lo toca. Lo mismo vale para todas las demás dependencias: las actualiza el gestor de paquetes, y solo cuando alguien lo ejecuta de verdad.
El listado de autoridades de certificación de confianza. Por defecto Node.js no usa el listado de autoridades de certificación del sistema operativo, sino su propio CA store integrado, y la documentación dice que se trata de una copia del listado de Mozilla fijada en el momento del lanzamiento. Así, un cambio como la reacción de este lanzamiento al certificado intermedio de eMudhra comprometido llega al programa solo junto con la actualización del runtime, y no junto con las actualizaciones del sistema operativo, salvo que el programa se haya configurado expresamente para usar el listado del sistema.
Cómo no dejar pasar el próximo lanzamiento
Node.js anuncia sus lanzamientos de seguridad de antemano, en su página de seguridad, e indica el día para el que está previsto el lanzamiento, y esta vez ocurrió exactamente así. Este miércoles no fue, por tanto, una sorpresa para quien vigila esa página: la actualización se podía dejar apuntada de antemano, en lugar de buscar el momento el mismo día.
En la práctica eso significa que alguien tiene que responder de esa vigilancia. En el hosting gestionado lo hace el proveedor, pero en un servidor propio, o en un proyecto que mantiene el propio equipo, conviene saber quién sigue los anuncios del proyecto, quién decide que la actualización se haga y quién comprueba que, una vez hecha, todo sigue funcionando. Si la respuesta a esas preguntas es «nadie en concreto», precisamente ahí está el mayor riesgo, y no en alguna de las diez vulnerabilidades.
Si para usted Node.js es solo un build tool
En muchos sitios web de Laravel y de WordPress, Node.js no funciona en el servidor en absoluto: ejecuta Vite, o un build tool semejante, que prepara los archivos CSS y JavaScript a partir del código fuente y después se detiene. En ese caso la situación difiere de la de una aplicación que atiende ella misma las peticiones, porque el proceso de build no responde a peticiones procedentes de internet ni descomprime datos que le envían visitantes a los que no conoce.
Que la situación difiera no significa que carezca de importancia. Los build tools funcionan en los ordenadores de quienes desarrollan y en el entorno de integración continua, descargan paquetes y abren conexiones con otros servidores, y las descripciones de las vulnerabilidades son demasiado breves para poder decir con seguridad cuáles de esos caminos están afectados. Conviene actualizar Node.js también allí, solo que en el orden correcto: primero los servidores en los que Node.js funciona en línea y, después, los ordenadores de quienes desarrollan y el entorno de integración continua.
Hay también un segundo motivo, y no tiene que ver con esta semana. El entorno de build suele quedarse en la versión de Node.js con la que el proyecto se inició en su día, y entonces llega un día en que una versión nueva de una herramienta simplemente se niega a funcionar con ella. El paso a una línea que tiene soporte ocurre entonces con prisa y en un momento que no conviene, así que es más fácil hacer el paso ahora, mientras todavía es un trabajo planificado.
Qué significó esto en nuestro hosting
Nuestro hosting gestionado es un espacio en nuestro propio servidor, y cada cliente elige allí la versión a través del panel de hosting. En nuestro servidor, las líneas de lanzamiento de Node.js 22 y 24 ya funcionan con las versiones corregidas, 22.23.4 y 24.22.1. A los clientes cuyos proyectos usan estas líneas no les hace falta hacer nada, salvo asegurarse de que el proceso se ha reiniciado después de la actualización.
También hay que decir con franqueza la otra cara. En el servidor siguen disponibles para elegir líneas que han llegado al fin de vida, y para ellas no hay parche de seguridad: ni en el nuestro ni en el de nadie más, porque Node.js no publica tal parche. Si para su proyecto se ha elegido alguna de esas líneas, actualizar significa pasar a la línea 22 o a la 24, y ese paso conviene hacerlo junto con una comprobación de que, después, todo funciona como funcionaba antes.
Nuestro hosting gestionado empieza desde 45 € al mes, y los runtimes que se mantienen son parte de aquello por lo que se paga esa cantidad. Si su aplicación todavía funciona sobre Node.js 18 o 20, hablemos del paso antes de que el día de algún lanzamiento de seguridad posterior obligue a hacerlo.
Preguntas frecuentes.
¿Cuál es la versión segura de Node.js?
Son seguras 22.23.4, 24.22.1 y 26.12.1, o las versiones posteriores de la misma línea de lanzamiento. Todo lo que dentro de su propia línea sea más antiguo está afectado. Para una versión cuya línea ha llegado al fin de vida, por ejemplo Node.js 18 o 20, no existe versión segura alguna, porque para ellas no se publican parches.
Tengo Node.js 18 o 20. ¿Qué hago?
Ambas líneas han llegado al fin de vida: la línea 18 el 30 de abril de 2025 y la línea 20 el 30 de abril de 2026. No hay parche de seguridad para ellas, y no lo habrá, así que la única salida es pasar a una línea que todavía tiene soporte. La línea 24 recibirá parches de seguridad hasta el 30 de abril de 2028, y la línea 22 hasta el 30 de abril de 2027. Conviene probar el paso primero en un entorno de pruebas.
¿Esta actualización de seguridad de Node.js es lo mismo que PHP2Shell?
No. Los dos sucesos cayeron el 21 de octubre, pero son distintos. PHP2Shell fueron dos vulnerabilidades críticas en el propio PHP. El lanzamiento de seguridad de Node.js se había anunciado de antemano, sus vulnerabilidades más graves están valoradas como altas, y el anuncio no menciona ataques en el entorno real.
¿Basta con actualizar Node.js si la aplicación ya está en marcha?
No. Hay que reiniciar el proceso. Un proceso que ya está en marcha sigue usando el Node.js con el que se inició. Si la aplicación está dentro de una container image de Docker, o se distribuye como un único archivo ejecutable (single executable application, SEA), el propio Node.js va integrado en ella, y hay que reconstruirla con la versión corregida.
En nuestro sitio web de Laravel o WordPress, Node.js solo sirve para construir con Vite. ¿Nos afecta?
Menos que a una aplicación que atiende ella misma las peticiones, porque el proceso de build no responde a peticiones procedentes de internet. Aun así, los build tools descargan paquetes y abren conexiones con otros servidores, así que conviene actualizar Node.js también en los ordenadores de quienes desarrollan y en el entorno de integración continua, y solo después de los servidores.
¿Hay una solución alternativa si no se puede actualizar de inmediato?
El anuncio de Node.js no menciona soluciones alternativas. La única recomendación es usar una versión que tenga soporte, conforme al calendario de lanzamientos. Para las versiones que han llegado al fin de vida, Node.js menciona un soporte comercial que ofrecen los socios del OpenJS Ecosystem Sustainability Program.
¿Cómo se sabe qué versión de Node.js usa la aplicación en un hosting con cPanel?
En la sección Software → Setup Node.js App, donde cada aplicación tiene su propia fila con la versión elegida. La orden node -v en la terminal puede mostrar una versión distinta de la del ajuste de la aplicación, así que mire precisamente la fila de la aplicación.
Servidores, hosting y mantenimiento en la UE — Fráncfort, Helsinki o Riga, con monitorización 24/7. Gestión completa: actualizaciones, seguridad y rendimiento, copias de seguridad automáticas con restauración probada, certificados SSL, CDN y protección DDoS. Migramos desde su proveedor de hosting actual sin interrupciones y escalamos según la carga.
Más artículos.