В популярной библиотеке vm2, предназначенной для изолированного выполнения недоверенного JavaScript-кода, выявлена целая серия критических уязвимостей. Все одиннадцать проблем получили максимальный балл по шкале CVSS (стандартная система оценки опасности программных ошибок). Две из этих уязвимостей до сих пор не исправлены, что ставит под удар тысячи приложений, использующих vm2 на серверах. Речь идёт о полном обходе песочницы: атакующий может выполнить произвольные команды на хост-системе, минуя все защитные механизмы.
Детали уязвимостей
vm2 - одна из самых распространённых библиотек в экосистеме Node.js. Её применяют для запуска сторонних скриптов в мультитенантных платформах (где код разных клиентов выполняется на одном сервере), в плагинных системах, на серверных движках и в инструментах непрерывной интеграции. По замыслу разработчиков, код, запущенный внутри конструкций VM.run() или NodeVM.run(), не может получить доступ к файловой системе, процессам или сетевому окружению хоста. Обнаруженные уязвимости полностью разрушают эту гарантию.
Технические детали выглядят так. Большинство проблем связано с внутренним механизмом "моста" (bridge) - прослойкой, которая управляет передачей ссылок на объекты между контекстом песочницы и контекстом хост-системы. Злоумышленник манипулирует стандартными встроенными примитивами JavaScript: методами __lookupGetter__, Buffer.apply, util.inspect, объектом Promise, конструкцией SuppressedError, а также инструкцией try_table из WebAssembly (низкоуровневой платформы для выполнения кода в браузере). С помощью таких трюков атакующий получает доступ к объекту Function.prototype, который принадлежит хост-контексту, а не песочнице. А затем создаёт новые функции, исполняемые уже на стороне хоста. Как только такой объект получен, достаточно вызвать child_process.execSync() - и любой код запускается на сервере с правами приложения, использующего vm2.
Одиннадцать уязвимостей были внесены в базу CVE (международный каталог идентификаторов уязвимостей) за короткий промежуток времени. Разработчик библиотеки под ником patriksimek опубликовал исправления в версиях 3.11.0 и 3.11.1, однако два последних отчёта (CVE-2026-44008 и CVE-2026-44009) остаются без патча на момент написания статьи. Они затрагивают все версии вплоть до 3.11.1 включительно.
Среди наиболее примечательных отдельных уязвимостей стоит выделить CVE-2026-26956. Эта проблема возникает только в среде Node.js версии 25 и использует механизм обработки исключений WebAssembly JSTag. Атакующий вызывает функцию, которая преобразует символ в строку и порождает TypeError, а затем перехватывает ошибку на уровне C++ (в движке V8) с помощью инструкции try_table. В результате код получает неочищенный объект ошибки из контекста хоста - все защитные слои на уровне JavaScript оказываются бессильны.
Ещё одна интересная уязвимость - CVE-2026-43999. Она связана с логической ошибкой в белом списке встроенных модулей NodeVM. Разработчики часто применяют шаблон настройки builtin: ['*', '-child_process'], чтобы разрешить все встроенные модули, кроме child_process. Однако в таком случае модуль builtin неявно добавляется в список разрешённых. Поскольку Module._load() выполняется на уровне хост-системы, он может загрузить любой исключённый модуль, включая child_process. Это делает белый список бесполезным.
Уязвимость CVE-2026-44007 затрагивает приложения, которые используют опцию nesting: true. Эта опция внедряет саму vm2 внутрь песочницы, даже если require: false. Таким образом, код внутри песочницы может вызвать require('vm2') и создать новый экземпляр NodeVM с неограниченным доступом к встроенным модулям, что ведёт к полному выполнению команд на хосте.
Последствия для бизнеса и разработчиков серьёзны. Если злоумышленник может выйти из песочницы, он способен украсть данные других клиентов мультитенантной платформы, остановить работу серверов, внедрить полезную нагрузку (вредоносный код, выполняющийся на хосте) или использовать скомпрометированную машину для дальнейших атак. Учитывая, что vm2 используется в системах непрерывной интеграции, атака может скомпрометировать всю цепочку поставки программного обеспечения.
Что делать специалистам по информационной безопасности? В первую очередь необходимо немедленно обновить vm2 до версии 3.11.1. Однако это не решает проблему полностью: две уязвимости остаются неисправленными. Следует внимательно отслеживать репозиторий библиотеки на GitHub в ожидании новых патчей. Кроме того, учитывая систематический характер обходов песочницы во всех версиях vm2, эксперты рекомендуют рассмотреть замену библиотеки на более защищённые альтернативы. Среди них - isolated-vm, которая использует изоляцию на уровне процессов, и встроенная модель разрешений платформы Deno. Любое приложение, которое открывает песочницу vm2 для внешнего ввода от пользователей, должно рассматриваться как критически уязвимое до полного устранения проблемы.
Таким образом, эта история напоминает: даже проверенные инструменты изоляции кода могут содержать фундаментальные дефекты проектирования, которые позволяют атакующим обойти все ограничения. И пока разработчики vm2 работают над исправлениями, ответственность за безопасность ложится на команды, которые используют эту библиотеку в боевых средах.
Ссылки
- https://github.com/patriksimek/vm2/releases/tag/v3.11.0
- https://github.com/advisories/GHSA-grj5-jjm8-h35p
- https://github.com/advisories/GHSA-v37h-5mfm-c47c
- https://github.com/advisories/GHSA-qcp4-v2jj-fjx8
- https://github.com/advisories/GHSA-47x8-96vw-5wg6
- https://github.com/advisories/GHSA-vwrp-x96c-mhwq
- https://github.com/advisories/GHSA-947f-4v7f-x2v8
- https://github.com/advisories/GHSA-hw58-p9xv-2mjh
- https://github.com/advisories/GHSA-6785-pvv7-mvg7
- https://github.com/advisories/GHSA-mpf8-4hx2-7cjg
- https://github.com/advisories/GHSA-v27g-jcqj-v8rw
- https://github.com/advisories/GHSA-wp5r-2gw5-m7q7
- https://github.com/advisories/GHSA-cp6g-6699-wx9c