Трендовые github проекты в нашем телеграм канале. Подпишись → Когда зависимость начинает воевать
Протестное ПО (protestware) — это код, который мейнтейнер библиотеки намеренно добавляет ради идеологического высказывания. Финансовой выгоды за такой закладкой обычно нет, зато есть готовность сломать приложение, стереть данные или заблокировать пользователей по географическому признаку. Для команды, которая собирает продукт из десятков транзитивных зависимостей, это такой же риск цепочки поставок, как компрометация репозитория или атака Dependency Confusion.
Опасность в том, что protestware приходит от известного автора и в проверенном пакете. Антивирус его не подсвечивает, код-ревью пропускает, а срабатывает закладка позже — по дате, локали или ответу геолокационного сервиса.
Чем это грозит продукту
Полезная нагрузка protestware выходит далеко за рамки раздражающего баннера в консоли. В реальных инцидентах она:
- повреждала и удаляла файлы на диске;
- уводила CLI-приложения и серверы в бесконечный цикл, блокируя event loop;
- ограничивала работу пользователей из конкретных стран;
- распространяла несогласованные сообщения от имени проекта.
Отдельно стоит развести вредоносную логику и мирный протест. Баннер, ссылка на петицию или позиция автора на главной странице репозитория вредоносной составляющей не несут. Оценивать их стоит с точки зрения репутации и дальнейшей поддержки компонента, но к защите сборки это отношения не имеет.
Три показательных инцидента
node-ipc и peacenotwar. Библиотека межпроцессного взаимодействия node-ipc подтянула модуль peacenotwar как зависимость. При установке модуль определял страну по исходящему IP через сервисы геолокации и, если это была Россия или Беларусь, перезаписывал файлы на диске символами сердца через execSync и вызов cp/echo. На рабочем столе появлялся файл WITH-LOVE-FROM-AMERICA.txt. Закладка пряталась в хуке postinstall и в основном коде через динамический require('peacenotwar').
colors.js и faker.js. Популярная библиотека цветного вывода в терминал получила в lib/index.js бесконечный цикл с печатью не-ASCII символов, который срабатывал на любом require('colors'). Итог — отказ в обслуживании для всего, что подключает пакет на старте. Изменение внёс сам мейнтейнер, и случай стал хрестоматийным примером риска от единственного сопровождающего критичного компонента.
es5-ext. Низкоуровневые утилиты ECMAScript 5, которые используются в webpack. Мейнтейнер добавил проверку: если системное время между 22:00 и 06:00 или локаль ru_RU, вызов require('es5-ext') уводил CPU в бесконечный цикл while (Date.now() < ...). Снова DoS, снова активация по условию среды.
Где прячется нагрузка и что её запускает
Вредоносная логика в protestware обычно живёт в одном из мест:
- код времени исполнения — срабатывает при вызове функции;
- хуки жизненного цикла npm — запускаются при установке пакета;
- скрипты сборки;
- тест-скрипты;
- метаданные пакета: чтение из
package.jsonи подгрузка инструкций с удалённого сервера.
Триггером активации служат параметры окружения:
- геолокация по IP: запросы к
ipinfo.io,ip-api.com, локальные geoip-базы; - системная локаль, часовой пояс, раскладка клавиатуры;
- переменные окружения:
process.env.USER,HOME,NODE_ENV, CI-переменные вродеGITLAB_CI; - hostname, доменное имя сети, имя пользователя ОС;
- текущие дата и время.
Последствия затрагивают продукт целиком: падение критических сервисов, сломанные CI/CD-конвейеры, потеря данных, остановка бизнес-процессов и нарушение SLA. Плюс расходы на расследование и восстановление.
Как это попадает в контур разработки
Самый частый путь — обновление уже используемого пакета. Новая версия транзитивной зависимости заезжает в сборку через npm, pip или другой менеджер, и вредоносный код оказывается внутри без участия разработчиков. Тот же сценарий работает при обновлении плагинов, линтеров и инструментов CI/CD.
В open source добавляется компрометация аккаунта мейнтейнера: получив доступ к репозиторию или реестру, злоумышленник публикует версию с закладкой. Ещё вариант — Dependency Confusion, когда внешний пакет с именем внутренней зависимости оказывается предпочтительнее приватного из-за настроек менеджера пакетов.
Признаки и инструменты обнаружения
Универсального детектора нет, но есть индикаторы, требующие ручного разбора:
- проверки географического расположения пользователя;
- сетевые запросы к API и геосервисам, не связанным с функциональностью библиотеки;
- операции удаления или модификации пользовательских данных, выходящие за назначение компонента;
- обфусцированный код в библиотеке, которой обфускация не нужна.
Помогает анализ цепочки поставок на нескольких уровнях:
- OSA — предварительная проверка open source до внедрения, в том числе сверка со списками «токсичных» репозиториев.
- SCA и SBOM — полный перечень компонентов, отслеживание новых версий, выявление известных вредоносных пакетов.
- Статический анализ — поиск конструкций вокруг геолокации (
geoip,country,locale,ip-api), удаления данных (rm -rf,delete,wipe,overwrite), запуска внешних команд и динамической загрузки кода. - Динамический анализ — контроль файловой активности, сетевых соединений и процессов, запуск в изолированной среде: контейнер, ВМ, sandbox.
- Мониторинг репозиториев — смена владельцев, новые мейнтейнеры, необычно крупные коммиты перед релизом, массовые правки зависимостей.
Реакция на найденную закладку
- Изолировать подозрительный пакет: остановить автообновления, зафиксировать текущую конфигурацию, оценить влияние, найти источник.
- Заблокировать скомпрометированную версию. Если она уже в продукте — исключить её из сборки.
- Откатиться на более раннюю версию, предварительно убедившись, что там нет той же логики.
Дальше — форк с самостоятельной поддержкой, если компонент критичен, или полная замена, если ресурсов на форк нет.
Меры защиты сборки
- Zero Trust для зависимостей. Происхождение и безопасность внешнего компонента подтверждаются независимо от его популярности.
- Регулярный аудит. Неиспользуемые и заброшенные библиотеки удаляются — каждая из них остаётся вектором атаки.
- Фиксация версий. Пиннинг снижает вероятность неожиданных изменений во время сборки.
- Изоляция сборки. Вредоносный код из одной сборки не дотягивается до продуктовой среды, хост-системы и следующих сборок.
- Подписание артефактов. Подтверждает происхождение компонентов и усложняет подмену пакетов.
- Внутренний репозиторий артефактов. Новые версии проходят сканирование, контроль происхождения и, при необходимости, ручное утверждение до попадания в прод.
В качестве опоры для процессов подходят NIST SSDF (практики безопасной разработки и управления зависимостями), SLSA (модель зрелости supply chain с защитой конвейера сборки и верификацией происхождения) и OpenSSF Scorecard (оценка практик репозитория: код-ревью, подпись коммитов, защита веток).
Количество звёзд и размер сообщества гарантий не дают. Контролировать нужно весь сторонний код: анализ open source, композиционный, статический и динамический анализ, контроль происхождения артефактов и организационные правила управления зависимостями.