Библиотека Tinypool, через которую приложения на Node.js распределяют задачи между рабочими потоками, содержит уязвимость в методе запуска этих задач. Ошибка позволяет удалённому злоумышленнику изменить атрибуты прототипа объекта, а затем выполнить на сервере произвольный код. Затронуты версии до 2.1.0 включительно. Разработчики закрыли проблему в выпуске 2.1.2, однако рабочий эксплойт лежит в открытом доступе.
Уязвимость CVE-2026-104849 в библиотеке Tinypool
Приложение передаёт пулу объект с параметрами задачи. Tinypool не проверяет, какие ключи в этом объекте пришли, и переносит их во внутренние структуры. Подставные ключи меняют прототип - общий шаблон, от которого объекты наследуют свойства. После подмены часть проверок перестаёт работать, а выполнение уходит по ветке, выбранной атакующим.
Класс ошибок называют загрязнением прототипа. Банк данных угроз безопасности информации описывает его как неправильно контролируемую модификацию атрибутов прототипа объекта. Второй тип ошибки - неверное управление генерацией кода, то есть внедрение кода. Два механизма складываются в одну последовательность. Сначала злоумышленник получает контроль над свойствами объекта, затем превращает это в исполнение своего кода.
Атака не требует учётной записи и действий пользователя. По вектору CVSS 3.1 уязвимость набирает 9,8 балла, по CVSS 4.0 - 9,5. Банк данных относит её к критическому уровню опасности. Оценка объясняется просто: успешная эксплуатация бьёт по конфиденциальности, целостности и доступности данных одновременно.
В карточке уязвимости указаны два способа эксплуатации. Первый - инъекция, то есть внедрение враждебного содержимого в данные, которые обрабатывает приложение. Второй - манипулирование сроками и состоянием, или состояние гонки: результат зависит от того, в каком порядке выполняются одновременные обращения к общему объекту. Оба сценария укладываются в удалённый вектор, поэтому злоумышленнику не нужен физический доступ к машине.
Проблема касается приложений, которые передают в пул данные из внешних источников. Скрипт, загруженный пользователем, содержимое файла или ответ стороннего сервиса попадают в параметры задачи, и вместе с ними в объект проникают лишние ключи. Отдельная сложность в том, что библиотека часто оказывается в проекте не напрямую, а как зависимость другого пакета. Тогда обновление требует просмотреть всё дерево зависимостей, а не только верхний уровень.
Получив выполнение кода, атакующий действует с правами процесса приложения. Ему доступны те же данные и сетевые ресурсы, что и самому сервису. Если процесс запущен с широкими правами, последствия выходят за границы одной задачи: под угрозой оказываются соседние сервисы на той же машине и учётные данные, которые приложение использует для подключения к базам и внешним API.
Дата выявления - 23 августа 2026 года. Разработчики подтвердили проблему и устранили её. Исправление вышло в релизе 2.1.2, подробности опубликованы в бюллетене проекта на GitHub. Версии ниже 2.1.2 остаются уязвимыми, поэтому перезапуска сервиса без обновления недостаточно.
Первое действие для администраторов - обновить Tinypool до 2.1.2. Проверить нужно и транзитивные зависимости, ведь уязвимая копия может остаться в глубине дерева пакетов. Если обновление откладывается, ограничьте набор полей, которые приложение передаёт в пул: опишите допустимую схему и отбрасывайте всё лишнее. Снизить цену ошибки помогает изоляция процессов, выполняющих задачи, - у них меньше прав, чем у основного приложения.
Загрязнение прототипа остаётся одним из самых частых классов ошибок в экосистеме JavaScript. На этапе разработки оно редко выглядит опасным, потому что приходит через данные, а не через явные вызовы. Для Tinypool последствия оказались максимальными: удалённое выполнение кода и оценки выше девяти баллов по всем версиям CVSS.