Каждый npm install — русская рулетка. Сотни библиотек от незнакомцев летят в проект, и любая может быть вредоносной

leer en español

Каждый npm install — русская рулетка. Сотни библиотек от незнакомцев летят в проект, и любая может быть вредоносной

Подробности свежего руководства ENISA: как защититься от кода, который никто не проверял.

image

Один пакет в npm, pip или Maven редко остается одним пакетом. За привычной командой установки обычно тянется длинная цепочка сторонних библиотек, которые автоматически попадают в проект вместе с прямыми и транзитивными зависимостями. В марте 2026 года ENISA выпустило техническое руководство по безопасному использованию менеджеров пакетов и подробно разобрало, почему такая практика расширяет поверхность атаки почти незаметно для самих команд разработки.

Проблема давно вышла за рамки удобства и скорости. Менеджеры пакетов действительно позволяют быстро добавить готовую функцию в приложение, не писать все с нуля и не собирать компоненты вручную. Но вместе с экономией времени разработчик получает в среду исполнения и сборки чужой код, который команда не писала, часто не читала и почти никогда не проверяла целиком. Причем объем такого кода может оказаться намного больше, чем кажется в момент установки.

Каждая новая библиотека встраивается в граф зависимостей проекта. После этого в окружении появляются не только прямые зависимости, которые разработчик выбрал сознательно, но и дополнительные модули, подтянутые автоматически. Часть таких компонентов может вообще не использоваться при работе программы, однако даже неиспользуемый модуль сохраняет уязвимости, историю сопровождения и риски, связанные с доверием к его автору и репозиторию.

ENISA рассматривает два основных класса угроз внутри таких экосистем. Первый связан с самими пакетами: ошибки в коде, слабая архитектура, небезопасные настройки, заброшенные библиотеки без сопровождения. Второй класс касается атак на цепочку поставок программного обеспечения, когда злоумышленник не ищет баг в готовом приложении, а пытается внедрить вредоносный код раньше, на этапе публикации, обновления или разрешения зависимостей.

Особенно опасны популярные библиотеки. Один широко используемый пакет может присутствовать в десятках тысяч проектов и стать общей опорой для большого числа фреймворков, сервисов и приложений. В такой схеме уязвимость в одном распространенном компоненте быстро выходит далеко за пределы исходного репозитория. Проблема начинает расходиться по цепочке вниз и затрагивает уже не один продукт, а заметную часть всей экосистемы.

С заброшенными пакетами ситуация не лучше. Библиотека может годами оставаться доступной в публичном репозитории, хотя автор давно перестал выпускать исправления и следить за безопасностью. Проект, который продолжает опираться на такой компонент, наследует все старые проблемы и часто не получает патчей месяцами или даже дольше. На практике это означает, что уязвимый код сохраняется в рабочей среде просто потому, что когда-то оказался удобной зависимостью.

Отдельный риск создают атаки на цепочку поставок. В такой модели злоумышленник публикует вредоносный пакет, получает доступ к учетной записи мейнтейнера или вмешивается в процесс разрешения зависимостей. После этого опасный компонент может попасть в проект через обычную установку или обновление, без ручной проверки внутреннего содержимого. Автоматизация, которая обычно помогает разработке, в таком сценарии начинает работать в пользу атакующего и быстро разносит вредоносный код по downstream-приложениям.

ENISA связывает защиту не с одной точкой контроля, а со всем жизненным циклом зависимости. Руководство делит работу на четыре этапа: выбор пакета, интеграция в проект, постоянный мониторинг и устранение выявленных проблем. Такой подход важен потому, что риск не заканчивается в момент установки. Он только начинается.

На этапе выбора команда должна смотреть не только на популярность библиотеки или удобство API. Важны происхождение пакета, активность мейнтейнеров, история уязвимостей, репутация репозитория и наличие признаков нормального сопровождения. Дополнительную роль играет проверка криптографических подписей и работа только с доверенными реестрами. По сути, вопрос стоит так: можно ли вообще пускать конкретный компонент в проект еще до первой команды установки.

Интеграция требует уже других мер. ENISA рекомендует фиксировать состав проекта через Software Bill of Materials, то есть перечень компонентов, входящих в сборку. Для стабильности среды важны lock-файлы зависимостей и проверка хешей, чтобы набор пакетов оставался одинаковым в разных окружениях. В цепочки непрерывной интеграции логично встраивать сканирование уязвимостей, чтобы известные проблемы обнаруживались не после релиза, а во время сборки.

После установки работа не заканчивается. Команда должна следить за новыми публикациями CVE, изменениями в статусе версий, активностью сопровождающих и признаками того, что пакет устаревает или меняет владельца. Такой мониторинг помогает увидеть риск до того, как он превратится в инцидент. Для зависимостей, на которых держатся критичные части системы, регулярное отслеживание уже давно стало не желательной мерой, а базовой практикой.

Когда уязвимость уже обнаружена, начинается этап устранения. Здесь недостаточно просто заметить запись в базе CVE. Разработчикам нужно понять, достижима ли проблема в конкретной системе и можно ли реально использовать ее в рабочем контексте. После такой оценки команда решает, что делать дальше: обновить пакет, заменить библиотеку на альтернативу или наложить патч. Универсального ответа здесь нет, но без анализа эксплуатируемости реакция часто превращается либо в панику, либо в опасное бездействие.

В руководстве есть еще один важный акцент, который напрямую связан с текущими изменениями в разработке. ENISA отмечает, что ИИ-инструменты все активнее участвуют в написании кода и все чаще предлагают готовые библиотеки прямо по ходу работы. Большие языковые модели могут рекомендовать зависимости, которые разработчик не изучал и не выбирал осознанно. В результате в проект попадает новый код, но решение о его добавлении фактически принимает не человек, а подсказка в интерфейсе.

Для команд, которые уже встроили ИИ-помощников в разработку, из этого следует довольно прямой вывод: любая библиотека, предложенная моделью, должна проходить ту же проверку, что и пакет, найденный вручную. Никаких отдельных поблажек для рекомендаций от LLM здесь быть не должно. Иначе автоматизация начинает незаметно наращивать зависимость от компонентов, происхождение и безопасность которых никто толком не оценивал.

Итак, главная мысль в том, что цепочки зависимостей, которые создают менеджеры пакетов, уже стали базовой частью современной разработки. Отказаться от них почти невозможно. Но каждая новая установка расширяет цепочку поставок за пределами самого приложения. Поэтому безопасная работа с зависимостями должна охватывать весь путь пакета, от выбора и установки до мониторинга и замены после появления уязвимости. Без такого контроля одна удобная команда установки слишком легко превращается в чужой код внутри собственного проекта.