Похоже, за n8n взялись всерьез (ну... неудивительно). Если дело так пойдет и дальше, придется заводить под их уязвимости отдельную рубрику.
Разбор упомянутых CVE в деталях можно почитать здесь, «из первых рук», так сказать. В чем суть, вкратце. Обе RCE — ответочка от jFrog на уже реализованные разработчиками n8n меры по устранению ранее обнаруженных уязвимостей, которые в итоге и привели к новым CVE-2026-1470 и CVE-2026-0863. Дело в том, что когда возможность выполнения пользователями <относительно> произвольного кода становится официальной фичей, вопрос безопасной реализации подобной функциональности слегка усложняется. Разработчики n8n пошли по пути синтаксической валидации пользовательского кода на уровне AST в обоих случаях (JavaScript, Python): код разбирается в синтаксическое дерево, дерево обходится визитором, осуществляющим детектирование потенциально опасных узлов.
И это — фиговое решение, как минимум по двум причинам.
1️⃣ Во-первых, по своей сути — это контроль по черным спискам. Собственно, патчи к этим уязвимостям (раз, два) разработчики свели к добавлению в эти списки техник атак, продемонстрированных ресерчерами jFrog. Сколько ещё вариантов поиграться с синтаксисом этих языков для подобных RCE существует прямо сейчас — думаю, jFrog'и скоро расскажут. А, как скоро в новых версиях языков появятся конструкции, не предусмотренные в черных списках n8n, но позволяющие выстроить гаджеты для вот таких RCE — покажет время.
2️⃣ Во-вторых, проверки на уровне AST — это синтаксическая валидация. У всех языков, помимо синтаксиса, есть ещё и семантика. А у динамических языков (коими являются, и JavaScript, и Python), некоторая её часть является сущностью времени выполнения. И эта часть НЕ МОЖЕТ быть эффективно проанализирована статическими проходами по синтаксическому представлению. Иными словами, даже белые списки (исходя из того, что в них было бы необходимо разрешить в свете соответствующих фич n8n) здесь не позволили бы закрыть все потенциальные проблемы.
🤓 Как правильно работать с такими кейсами?
Простых решений, здесь, увы можно не ожидать. По возрастанию
1️⃣ Если есть возможность влиять на язык, используемый для скриптов, то взять ограниченный валидацией по белым спискам (разрешенные синтаксические конструкции, пространства имен и типы) статический язык с сильной типизацией. Из известных мне языков на эту роль лучше всего подходит C# Scripting.
2️⃣ На этапе прохода по AST инструментировать код проверками на допустимость операций, которые будут осуществляться в рантайме, во время выполнения скрипта. В идеале библиотека рантайма и используемые сторонние библиотеки также должны быть инструментированы (реализацию можно подсмотреть в OpenTelemetry, например). В пределе — это приведет к разработке собственного RASP, заточенного под фичи скриптинга конкретного проекта.
3️⃣ Использовать собственноручно пропатченные интерпретаторы, допускающие только разрешенные синтаксис и семантику. Настолько сложно, что в большинстве случаев нецелесообразно.
Ну и, безотносительно способа первичной защиты: выполнять все пользовательские скрипты в изолированных контейнерах: как минимум — в Docker, как рациональный максимум — в условном FireCracker'е.
⚠ TL;DR: разработчики n8n думают, что устранили ещё две RCE, но есть нюанс. И простого способа его обойти у них нет.
#уязвимости
