
Proof-of-concept и лаборатория для побега из песочницы n8n 2.42.0: скрытые узлы Function/FunctionItem выполняют JS в основном процессе, что даёт аутентифицированным участникам RCE на хосте.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · n8n-function-vm2
n8n 2.42.0 - n8n GmbH
GHSA-j4p8-h8mh-rh8q перенёс n8n-nodes-base.code в дочерний процесс JS task-runner. Продакшн-запуск добавляет --disallow-code-generation-from-strings и --disable-proto=delete. Остаётся то, что они спрятали вместо переноса. Function.node.ts имеет hidden: true. FunctionItem тоже. LangChain Code тоже. Скрытие в палитре — это флаг UI. Сохранение/импорт JSON рабочего процесса всё ещё разрешает тип. Значение по умолчанию NODES_EXCLUDE — только Execute Command и Local File Trigger. Путь выполнения — это внутрипроцессный vm2 NodeVM 3.12.2 в основном процессе n8n.
Участник по умолчанию, который может создать рабочий процесс, может выполнить JS в основном процессе n8n. Скрытие — это не ACL.
| ID | CVE пока нет |
| CWE | CWE-94, CWE-269 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Продукт | n8n |
| Затронуто | по 2.42.0 (86c23326); остаток от GHSA-j4p8 |
| Аутентификация | аутентифицированный участник с правами создания/импорта/выполнения рабочих процессов |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Будучи участником по умолчанию, импортировать или создать рабочий процесс, узел которого имеет type равный n8n-nodes-base.function (или functionItem, или @n8n/n8n-nodes-langchain.code), и выполнить его. JS выполняется в основном процессе n8n.
Это RCE на хосте от имени UID n8n: секреты экземпляра, зашифрованные учётные данные других пользователей на диске, БД. Захват экземпляра участником в мультитенантной среде. Не OS LPE. Не без аутентификации. Code v2 на том же экземпляре не видит process таким образом.
Тот же продукт, родственный остаток: Databricks path join.
Сначала я прочитал волну GHSA от 16 сентября 2026 года, затем провёл десять поисков по тегу [email protected]. Песочница выражений, Code/Function/vm2, учётные данные, вебхуки, HTTP/SSRF, узел Git, community-пакеты, auth/SSO, инъекция узлов, публичный API. Большинство High из той волны закрыты на этой версии. Code не был завершён.
Правила обратной совместимости v3 уже помечают Function / FunctionItem как удалённые. На 2.42.0 они — остаток, а не предполагаемая долгосрочная песочница. Function также внедряет this.helpers, включая хелперы, которые JS-раннер перечисляет как неподдерживаемые. Мне не понадобился публичный гаджет vm2, чтобы доказать границу процесса.
Я развернул стандартный n8nio/n8n:2.42.0, зарегистрировал участника (не владельца экземпляра), импортировал n8n-nodes-base.function, выполнил его. Function pid=7 — это основной PID n8n. Тот же JS в Code v2: hasProcess: false. Дочерний процесс task-runner — pid 26. Свидетель N8N-FUNCTION-VM2-WITNESS.
Уже зафиксированные ошибочные пути: тип Function отклонён как скрытый/неизвестный (тогда узел фактически исключён); pid Function равен дочернему процессу task-runner (тогда он уже перенесён); Code v2 видит process (тогда раннер не является контролем); эксплойт-гаджет vm2, обратная оболочка, OS LPE. Театр. Свидетель — основной PID против hasProcess: false.
cd lab
./run.sh
Цель только http://127.0.0.1:18201. По умолчанию NODES_EXCLUDE. Атакующий — участник.
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
Добавьте n8n-nodes-base.function, n8n-nodes-base.functionItem и @n8n/n8n-nodes-langchain.code в значение по умолчанию NODES_EXCLUDE или направьте их через JsTaskRunnerSandbox так, как это уже делает Code v2. hidden в палитре недостаточно.
Function.node.ts · Code.node.ts · nodes.config.ts · task-runner-process-js.tsGNU Affero GPL v3.0. См. LICENSE. Только loopback-лаборатория. Без гарантий.