Node.js publicó hoy parches de seguridad para sus tres líneas activas. Son 10 vulnerabilidades, cuatro de gravedad alta. Si tienes una API, un bot o un worker corriendo en Node, vale la pena dedicarle un rato esta misma tarde.
Las versiones corregidas son 22.23.4, 24.22.1 y 26.12.1. No necesitas cambiar de línea: instala el parche de la que ya usas y listo. Si estás en una versión sin soporte (la 25, la 23, la 20), no va a salir ningún arreglo para ti y toca migrar a una línea mantenida.
Lo que más importa
De las diez, cuatro son de gravedad alta. Esto es lo que hace cada una, sin vueltas.
Brotli (CVE-2026-111497). Es una escritura fuera de límites en el decodificador de Brotli, un formato de compresión muy común en respuestas HTTP. El aviso dice que podría permitir ejecución remota de código y no da más detalles. Lo delicado es que no necesitas usar Brotli a propósito: fetch() descomprime solo las respuestas con Content-Encoding: br. Un análisis independiente que revisó el código de undici concluye que pedir Accept-Encoding: identity no te protege, porque un servidor malicioso puede contestar con Brotli de todos modos. Ese mismo análisis no logró comprobar la escritura fuera de límites con los datos de prueba del parche, y yo no vi un exploit público. Aun así, es la que yo actualizaría primero.
Verificación TLS con direcciones IP raras (CVE-2026-105483 y CVE-2026-106069). Una IPv4 se puede escribir de muchas formas: 127.1, 0127.0.0.1, con dígitos de ancho completo. Node normalizaba esos nombres y después los comparaba con los nombres DNS del certificado, así que un certificado con algo como 127.0.0.1 en su lista DNS podía pasar por válido para esos hosts. Para aprovecharlo, el atacante necesita un certificado emitido por una CA en la que tú confías, y el propio commit del arreglo dice que no es fácil de explotar. Donde más cuenta es en las conexiones salientes a hosts que vienen de afuera, como webhooks o URLs que pega un usuario.
DNS y el carácter NUL (CVE-2026-105482). Si le pasas a dns.resolve() un nombre con un \0 en el medio, la librería de C solo lee lo que hay antes. En la prueba del arreglo, example.com\0.trusted.corp termina consultando example.com. Te afecta si validas nombres por sufijo, por ejemplo "solo dominios que terminen en .miempresa.com".
La lista completa
| CVE | Qué es | Gravedad | Líneas |
|---|---|---|---|
| CVE-2026-105482 | dns.resolve corta los nombres con un carácter NUL |
Alta | 22, 24, 26 |
| CVE-2026-105483 | TLS: dígitos de ancho completo en una IP | Alta | 24, 26 |
| CVE-2026-106069 | TLS: host que se vuelve IP al normalizarlo | Alta | 22, 24, 26 |
| CVE-2026-111497 | Brotli: escritura fuera de límites | Alta | 22, 24, 26 |
| CVE-2026-105481 | HTTP keep-alive: procesa una respuesta escrita antes de la petición | Media | 22, 24, 26 |
| CVE-2026-106072 | TLS: una IPv4 no canónica se autentica con un nombre DNS del certificado | Media | 22, 24, 26 |
| CVE-2026-106074 | randomUUID() y randomInt() repiten valores si el proceso sale de un snapshot o de una SEA |
Media | 22, 24, 26 |
| CVE-2026-106070 | ZipFile devuelve bytes controlados por el atacante tras rechazar una cabecera | Baja | 26 |
| CVE-2026-106071 | Permission Model: permisos de archivos más amplios de lo debido con comodines | Baja | 26 |
| CVE-2026-106073 | Permission Model: se salta la comprobación con fs.realpathSync |
Baja | 22, 24, 26 |
Las dos del Permission Model solo importan si arrancas Node con --permission. La de randomUUID() te toca si distribuyes aplicaciones empaquetadas como ejecutable único (SEA) o con snapshots de arranque.
Lo de eMudhra
Este release también bloquea las cadenas de certificados que pasan por las CA intermedias comprometidas de eMudhra, y actualiza los certificados raíz a NSS 3.131.1. Si después de actualizar alguna conexión empieza a fallar con CERT_REVOKED, es el comportamiento esperado. No apagues la verificación TLS para taparlo.
Cómo actualizar
Empieza por mirar qué versión tienes:
bashnode -v
Ojo con esto: ese comando te dice qué Node usa tu terminal, no necesariamente el que usa tu servicio. Si corres la app con systemd o PM2, puede estar arrancando otro binario. Lo más confiable es que la propia aplicación registre la versión cuando arranca:
jsconsole.info('runtime-start', {
node: process.version,
execPath: process.execPath,
pid: process.pid
});
Después de desplegar, busca esa línea en los logs de cada réplica y de cada worker. Así te enteras si alguno quedó con el Node viejo.
Con nvm:
bashnvm install 24
nvm use 24
Con Docker o Dokploy: fija la versión y reconstruye. Si reconstruyes desde una caché vieja te quedas con la versión anterior, así que fuerza la descarga de la imagen:
bashdocker build --pull --no-cache -t mi-app:nueva .
docker run --rm mi-app:nueva node -v
Las imágenes oficiales node:24.22.1, node:22.23.4 y node:26.12.1 ya estaban en Docker Hub poco después del lanzamiento. En Dokploy, haz un redeploy con reconstrucción.
Con paquetes del sistema (apt, NodeSource): mira qué versión ofrece tu repositorio antes de asumir que ya está parchado. Algunas distribuciones corrigen sin cambiar el número de versión, así que pide el aviso de seguridad del paquete.
Con binarios de nodejs.org: descarga el de tu línea desde la página de descargas y verifica la suma de comprobación antes de instalarlo.
Y lo más importante: instalar no basta. Reinicia los procesos, porque un Node que ya estaba corriendo sigue con el código viejo hasta que lo reinicies.
Si no puedes actualizar todavía
Hay dos paliativos sencillos. No sustituyen el parche, pero te ayudan mientras tanto.
Para lo del carácter NUL, rechaza el nombre antes de resolverlo:
jsif (nombre.includes('\0')) {
throw new Error('Nombre de host inválido');
}
Para las IP raras, rechaza los hosts que no son una IP según Node pero se convierten en una al normalizarlos (esta comprobación la propone el análisis independiente que mencioné):
jsconst net = require('node:net');
const url = require('node:url');
const esIPNoCanonica = (host) =>
!net.isIP(host) && net.isIP(url.domainToASCII(host)) !== 0;
Úsalo solo con hosts que vengan de entradas externas.
Preguntas rápidas
¿npm audit me protege? No. npm audit revisa las dependencias de tu proyecto, no el runtime de Node. Son dos actualizaciones distintas.
¿Tengo que pasarme a Node 26? No. Cada línea tiene su parche: 22.23.4, 24.22.1 o 26.12.1. La 26 es la línea Current y las otras dos son LTS.
Mi versión ya no tiene soporte. ¿Estoy en peligro? Node avisa que las versiones sin soporte siempre quedan afectadas cuando sale un parche, porque ya no reciben arreglos. Planea la migración cuanto antes.
¿Esto significa que me hackearon? No. Una versión desactualizada solo te dice que te falta el parche. No dice si alguien llegó a entrar. Si ves procesos raros o accesos que no reconoces, guarda los logs y revisa.
Fuentes
- Aviso de Node.js: https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
- Notas de la versión 24.22.1: https://nodejs.org/en/blog/release/v24.22.1/
- Notas de la versión 22.23.4: https://nodejs.org/en/blog/release/v22.23.4/
- Notas de la versión 26.12.1: https://nodejs.org/en/blog/release/v26.12.1/
- Análisis independiente de lilting: https://lilting.ch/en/articles/nodejs-tls-dns-brotli-security-release
- Guía de Teramont: https://teramont.net/es/blog/nodejs-vulnerabilidades-octubre-2026-actualizar-vps

ES
EN