
Prueba de concepto y laboratorio para un escape de sandbox de n8n 2.42.0: los nodos ocultos Function/FunctionItem ejecutan JS en el proceso principal, otorgando a los miembros autenticados RCE en el host.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · n8n-function-vm2
Análisis: https://abraxaslabs.tech/research/n8n-function-vm2
n8n 2.42.0 - n8n GmbH
GHSA-j4p8-h8mh-rh8q trasladó n8n-nodes-base.code al proceso hijo task-runner de JS. El spawn en producción añade --disallow-code-generation-from-strings y --disable-proto=delete. Lo que queda son los nodos que ocultaron en lugar de trasladar. Function.node.ts tiene hidden: true. FunctionItem también. LangChain Code también. Ocultar en la paleta es solo un flag de la UI. El guardado/importación del JSON del workflow sigue resolviendo el tipo. El NODES_EXCLUDE por defecto solo incluye Execute Command y Local File Trigger. La ruta de ejecución es vm2 NodeVM 3.12.2 en proceso, dentro del proceso principal de n8n.
Un miembro con la configuración por defecto que puede crear un workflow puede ejecutar JS en el proceso principal de n8n. Oculto no es una ACL.
| ID | aún sin CVE |
| CWE | CWE-94, CWE-269 |
| CVSS | Alto: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Producto | n8n |
| Afectado | hasta 2.42.0 (86c23326); remanente de GHSA-j4p8 |
| Autenticación | miembro autenticado con permiso de crear/importar/ejecutar workflows |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Como miembro con la configuración por defecto, importar o crear un workflow cuyo type de nodo sea n8n-nodes-base.function (o functionItem, o @n8n/n8n-nodes-langchain.code) y ejecutarlo. El JS se ejecuta en el proceso principal de n8n.
Eso es RCE en el host con el UID de n8n: secretos de la instancia, el texto cifrado de las credenciales de otros usuarios en disco, la base de datos. De miembro multiinquilino a toma de control de la instancia. No es LPE del SO. No es sin autenticación. Code v2 en la misma instancia no ve process de esa forma.
Mismo producto, remanente hermano: Databricks path join.
Primero leí la oleada de GHSA del 16 de septiembre de 2026, luego diez cacerías sobre el tag [email protected]. Sandbox de expresiones, Code/Function/vm2, credenciales, webhooks, HTTP/SSRF, nodo Git, paquetes de la comunidad, auth/SSO, inyección de nodos, API pública. La mayoría de los Altos de esa oleada están cerrados en esta versión fijada. Code no estaba terminado.
Las reglas de cambios disruptivos de v3 ya marcan Function / FunctionItem como eliminados. En 2.42.0 son un remanente, no un sandbox previsto a largo plazo. Function además inyecta this.helpers, incluidos helpers que el runner de JS lista como no soportados. No necesité un gadget público de vm2 para demostrar la frontera del proceso.
Levanté un n8nio/n8n:2.42.0 estándar, registré un miembro (no el propietario de la instancia), importé n8n-nodes-base.function, lo ejecuté. El pid=7 de Function es el PID principal de n8n. El mismo JS en Code v2: hasProcess: false. El proceso hijo task-runner es el pid 26. Testigo N8N-FUNCTION-VM2-WITNESS.
Pistas falsas ya registradas: el tipo Function rechazado como oculto/desconocido (entonces el nodo sí está excluido); el pid de Function igual al del proceso hijo task-runner (entonces ya se había trasladado); Code v2 viendo process (entonces el runner no es el control); un gadget de exploit de vm2, una reverse shell, LPE del SO. Teatro. El testigo es el PID principal frente a hasProcess: false.
cd lab
./run.sh
Atacar solo http://127.0.0.1:18201. NODES_EXCLUDE por defecto. El atacante es miembro.
authenticated-as=member
function-fields pid=7 witness=N8N-FUNCTION-VM2-WITNESS
code-fields hasProcess=False pid=None
compare function_pid=7 code_pid=None main_pid=7 runner_pid=26 who=member
SUCCESS N8N-FUNCTION-VM2 who=member function_pid=7 code_pid=None main_pid=7 runner_pid=26 N8N-FUNCTION-VM2-WITNESS
Añade n8n-nodes-base.function, n8n-nodes-base.functionItem y @n8n/n8n-nodes-langchain.code al NODES_EXCLUDE predeterminado, o enrútalos a través de JsTaskRunnerSandbox tal como ya lo hace Code v2. La opción hidden de la paleta no es suficiente.
Function.node.ts · Code.node.ts · nodes.config.ts · task-runner-process-js.tsGNU Affero GPL v3.0. Consulta LICENSE. Solo para laboratorio de loopback. Sin garantía.