Простые шаги для безопасной работы с зависимостями программного обеспечения
Сторонние зависимости – один из основных каналов проникновения уязвимостей в цепочку поставки ПО. До 80% кода в современных приложениях составляют компоненты с открытым исходным кодом, при этом наибольшая часть этих компонентов остается без обновлений в течение года. За этот период ПО может “накопить” до 100 уязвимостей.
Базовые меры работы с зависимостями позволяют заметно снизить риски без серьёзных изменений процессов. Ниже приведены конкретные простые практики, которые повышают предсказуемость сборки и упрощают анализ безопасности проекта.
Фиксация версий через lock-файлы
Фиксировать версии зависимостей – это фундаментальный способ сделать сборку предсказуемой. Если проект использует “плавающие” версии, например latest, каждая новая сборка может подтягивать разные варианты библиотек, включая транзитивные зависимости, что повышает риск появления уязвимых версий.
Lock-файлы фиксируют точные версии всех зависимостей на момент сборки. Например, в экосистеме JavaScript используют package-lock.json или yarn.lock, для Python – poetry.lock или Pipfile.lock. Они обеспечивают воспроизводимость сборки и упрощают анализ безопасности.
При работе с lock-файлами важно:
периодически обновлять их в контролируемом режиме;
проверять, что новые версии проходят тесты безопасности и совместимости.
Инструкции по созданию lock-файлов в популярных экосистемах описаны в нашей документации.
Ограничение install-скриптов
Многие пакетные менеджеры позволяют выполнять скрипты во время установки зависимостей (например, postinstall, preinstall, prepare). Они часто используются легитимно – для сборки нативных модулей, генерации файлов или настройки окружения. Однако именно этот механизм регулярно становится точкой входа для атак на цепочку поставки: вредоносный код выполняется автоматически в момент установки пакета, ещё до запуска приложения.
Поэтому рекомендуется ограничивать или полностью отключать выполнение install-скриптов для сторонних зависимостей. Например, в npm и Yarn можно использовать флаг --ignore-scripts, который запрещает выполнение подобных команд при установке пакетов. Если скрипты действительно необходимы, их стоит запускать вручную после проверки зависимости или разрешать только для доверенных пакетов.
Политика “возраста пакета”
Ограничение на минимальный возраст пакета помогает фильтровать потенциально небезопасные версии. Новые релизы библиотек могут содержать уязвимости, которые ещё не выявлены сообществом. Настройка правила, запрещающего использовать пакеты моложе недели или месяца, снижает риск ранних инцидентов.
В CodeScoring можно настроить соответствующую политику безопасности, чтобы автоматически блокировать слишком свежие версии пакетов. Эта мера почти не влияет на скорость разработки, но добавляет надёжный уровень защиты.
Мы считаем 14 дней разумным стартовым ориентиром для возраста пакета, но не универсальным правилом для всех проектов. Такой порог снижает риск быстро распространяющихся атак на цепочку поставки ПО, однако его нужно внедрять осознанно. Транзитивные зависимости даже у старых компонентов могут подтягиваться без жестко зафиксированных версий. Поэтому важно не только задать минимальный возраст пакета, но и уметь инструментально выявлять такие ситуации, обрабатывать исключения и контролировать фактический состав сборки.
Рекомендации и примеры настройки данной политики также доступны в документации.
Проверка контрольных сумм
Даже при фиксированных версиях полезно проверять целостность скачанных пакетов. Большинство пакетных менеджеров поддерживают проверку хэшей, например:
Это защищает от случайной подмены или повреждения пакетов, особенно если зависимости скачиваются из внешних репозиториев.
Регулярная ревизия зависимостей
Lock-файлы и политика возраста не решают проблему появления новых уязвимостей в уже зафиксированных пакетах. Поэтому полезно проводить регулярную проверку зависимостей на актуальность и известные проблемы.
CodeScoring позволяет настроить рекуррентное сканирование, которое автоматически проверяет проекты на новые уязвимости, обеспечивая постоянный контроль над безопасностью зависимостей.
Итоги
При работе с зависимостями понимание контекста проекта имеет ключевое значение. Даже самые продвинутые инструменты анализа уязвимостей дают лучший результат, когда процессы сборки и управления пакетами настроены осознанно и последовательно.
Важно помнить, что транзитивные зависимости часто скрывают наибольшие риски, а уязвимости могут появляться не только в популярных пакетах, но и в малозаметных модулях, на которые проект опирается косвенно. Системное наблюдение за этими зависимостями и интеграция анализа в CI/CD позволяет максимально снизить “шум” от ложноположительных результатов и получать актуальные данные для принятия решений.