
Proof-of-concept e lab per un sandbox escape di n8n 2.42.0: i nodi Function/FunctionItem nascosti eseguono JS nel processo principale, concedendo ai membri autenticati RCE sull'host.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · n8n-function-vm2
Write-up: https://abraxaslabs.tech/research/n8n-function-vm2
n8n 2.42.0 - n8n GmbH
GHSA-j4p8-h8mh-rh8q ha spostato n8n-nodes-base.code sul processo figlio del task-runner JS. In produzione lo spawn aggiunge --disallow-code-generation-from-strings e --disable-proto=delete. Ciò che resta sono i nodi che hanno nascosto invece di spostare. Function.node.ts è hidden: true. Lo stesso vale per FunctionItem. E per LangChain Code. Nascondere dalla palette è solo un flag dell'interfaccia. Il salvataggio/importazione del JSON del workflow risolve comunque il tipo. Il valore predefinito di NODES_EXCLUDE include solo Execute Command e Local File Trigger. Il percorso di esecuzione è vm2 NodeVM 3.12.2 in-process nel processo principale di n8n.
Un membro con i permessi predefiniti che può creare un workflow può eseguire JS nel processo principale di n8n. Nascosto non significa ACL.
| ID | nessuna CVE al momento |
| 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 |
| Prodotto | n8n |
| Affetto | fino alla 2.42.0 (86c23326); residuo di GHSA-j4p8 |
| Auth | membro autenticato con permessi di creazione/importazione/esecuzione di workflow |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
In qualità di membro con i permessi predefiniti, importare o creare un workflow il cui nodo type è n8n-nodes-base.function (o functionItem, o @n8n/n8n-nodes-langchain.code) ed eseguirlo. Il JS viene eseguito nel processo principale di n8n.
Si tratta di RCE sull'host con l'UID di n8n: segreti dell'istanza, ciphertext delle credenziali degli altri utenti su disco, il DB. Da membro multi-tenant alla compromissione dell'istanza. Non è LPE a livello di OS. Non è non autenticato. Code v2 sulla stessa istanza non vede process in quel modo.
Stesso prodotto, residuo affine: Databricks path join.
Ho letto prima l'ondata di GHSA del 16 settembre 2026, poi dieci ricerche sul tag [email protected]. Sandbox delle espressioni, Code/Function/vm2, credenziali, webhook, HTTP/SSRF, nodo Git, pacchetti della community, auth/SSO, node injection, API pubblica. La maggior parte delle vulnerabilità High di quell'ondata sono chiuse su questa versione. Code non era stato completato.
Le regole delle breaking change della v3 marcano già Function / FunctionItem come rimossi. Sulla 2.42.0 sono un residuo, non una sandbox intenzionale a lungo termine. Function inietta anche this.helpers, inclusi helper che il runner JS elenca come non supportati. Non mi è servito un gadget pubblico di vm2 per dimostrare il confine del processo.
Ho avviato l'immagine stock n8nio/n8n:2.42.0, registrato un membro (non il proprietario dell'istanza), importato n8n-nodes-base.function, eseguito. Il pid=7 di Function è il PID principale di n8n. Lo stesso JS in Code v2: hasProcess: false. Il processo figlio del task-runner è il pid 26. Witness N8N-FUNCTION-VM2-WITNESS.
Vicoli ciechi già registrati: tipo Function rifiutato come nascosto/sconosciuto (allora il nodo è effettivamente escluso); pid di Function uguale a quello del processo figlio del task-runner (allora è già stato spostato); Code v2 che vede process (allora il runner non è il controllo); un gadget di exploit vm2, una reverse shell, LPE a livello di OS. Teatro. Il witness è PID principale vs hasProcess: false.
cd lab
./run.sh
Prendi di mira solo http://127.0.0.1:18201. NODES_EXCLUDE predefinito. L'attaccante è un membro.
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
Aggiungere n8n-nodes-base.function, n8n-nodes-base.functionItem e @n8n/n8n-nodes-langchain.code al valore predefinito di NODES_EXCLUDE, oppure instradarli tramite JsTaskRunnerSandbox come già fa Code v2. L'opzione hidden della palette non è sufficiente.
Function.node.ts · Code.node.ts · nodes.config.ts · task-runner-process-js.tsGNU Affero GPL v3.0. Vedi LICENSE. Solo per laboratorio su loopback. Nessuna garanzia.