SBOM против вредоносных пакетов: как проверить зависимости до релиза

📋 Кратко

SBOM помогает увидеть состав приложения и связи между его компонентами. Но перечень зависимостей сам по себе не показывает вредоносный код. До релиза команда проверяет версии, источники, хеши, скрипты установки, изменения в исходниках и поведение сборки. Такой подход снижает риск попасть в поставку с опасным пакетом.

⏱ 10 минут чтения│сложность

Зависимость попадает в приложение задолго до выпуска. Разработчик добавляет пакет в проект. Сборочная система получает его из внешнего источника. Затем пакет входит в архив, контейнер или установщик.

Если компонент содержит вредоносный код, проблема возникает ещё до публикации продукта. Позже команда видит только последствия. Пакет может читать секреты, менять файлы или обращаться к внешнему серверу.

SBOM помогает ответить на первый вопрос: что именно входит в поставку? Но этот перечень не доказывает безопасность компонентов. Его нужно соединять с анализом уязвимостей, проверкой происхождения и контролем сборки.

Главная мысль: SBOM описывает состав поставки. Он не заменяет проверку кода, пакетов и поведения сборочного процесса.
SBOM раскрывает полный состав цифрового продукта
SBOM раскрывает полный состав цифрового продукта

🔍 Что именно показывает SBOM

SBOM — это перечень компонентов программного продукта. В нём указывают название пакета, версию и связи с другими элементами. Такой список помогает увидеть не только прямые, но и транзитивные зависимости.

Один пакет может нести разные типы риска
Один пакет может нести разные типы риска

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

SBOM также помогает связать компонент с конкретной сборкой. Это важно при выпуске нескольких вариантов приложения. Один архив может содержать другой набор библиотек, чем соседний.

Перечень полезен и после релиза. Если появляется информация об опасной версии, команда ищет её в уже выпущенных продуктах. Без точного состава такая проверка превращается в догадку.

Почему перечень не равен проверке

SBOM не читает смысл каждой строки кода. Он не определяет, является ли пакет подделкой. Он также не видит подозрительное поведение скрипта установки без дополнительного анализа.

Один и тот же пакет может быть уязвимым, устаревшим или вредоносным. Это разные состояния. Уязвимость означает слабое место в коде. Устаревшая версия может не иметь нужного исправления.

Вредоносный пакет создают или изменяют с целью навредить. В нём может не быть записи в базе уязвимостей. Поэтому команда проверяет не только номер версии.

Что сделать сейчас: формируйте SBOM для каждого выпуска и сохраняйте его вместе с номером сборки.

⚠️ Чем отличаются уязвимый, устаревший и вредоносный пакет

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

Скрытые зависимости формируют полный путь поставки
Скрытые зависимости формируют полный путь поставки

В качестве примера можно рассмотреть библиотеку Apache Commons FileUpload. Для неё существует запись CVE-2016-1000031. Такая запись показывает известную проблему компонента, но не говорит, что пакет вредоносен.

Другой пример связан с Apache Log4j 2.x. Запись CVE-2017-5645 показывает необходимость учитывать транзитивные зависимости. Библиотека может прийти не из файла с прямым списком проекта.

Низкоуровневые компоненты тоже требуют внимания. В цепочке сборки может присутствовать zlib версии 1.2.8. Для этой версии указана CVE-2016-9841. Такой пример показывает роль библиотек, которые разработчик не подключает напрямую.

Устаревший пакет не обязательно имеет известную уязвимость. Но его сопровождение может остановиться. Исправления тогда не приходят. Команда фиксирует причину использования старой версии и план обновления.

Вредоносная зависимость ведёт себя иначе. Она может выглядеть новой и не иметь известных CVE. Опасность появляется из-за кода, владельца пакета, изменения архива или скрипта установки.

Правило проверки: запись в базе уязвимостей отвечает на один вопрос. Для оценки пакета нужны ещё источник, целостность, изменения и поведение.

Что сделать сейчас: разделите правила для уязвимых, устаревших и подозрительных компонентов.

🧩 Прямые и транзитивные зависимости

Прямая зависимость видна в файле проекта. Её проще обсуждать с разработчиком. Но она редко описывает полный состав приложения.

Происхождение и целостность требуют отдельной проверки
Происхождение и целостность требуют отдельной проверки

Транзитивная зависимость приходит через другой пакет. Она может использоваться только частью продукта. При этом она всё равно попадает в итоговый архив или контейнер.

Проблема усиливается, когда команда анализирует только верхний уровень списка. В таком случае опасный компонент остаётся незамеченным. SBOM должен отражать полное дерево поставки.

Отдельно проверяйте библиотеки обработки входных данных. В качестве примера подходит Expat. Для него указана CVE-2016-0718. Такая проверка нужна, даже если библиотека скрыта внутри другого продукта.

То же относится к среде выполнения. Уязвимость CVE-2017-1000158 затрагивает CPython 2.7.13 и более ранние версии. Команда учитывает не только код приложения, но и окружение, в котором он запускается.

Как читать дерево

Сначала выделите корневой продукт. Затем отметьте прямые пакеты. После этого раскройте каждую ветку до самого нижнего уровня.

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

Если библиотека больше не нужна, удаляйте её из дерева. Чем меньше компонентов, тем проще контроль. Уменьшается и число возможных путей для вредоносного кода.

Что сделать сейчас: запретите выпуск SBOM, в котором отсутствуют транзитивные зависимости.

🛠️ SPDX и CycloneDX: два формата для состава поставки

SBOM можно хранить в разных форматах. В практике часто используют SPDX и CycloneDX. Оба формата помогают описать компоненты и связи между ними.

Подозрительные зависимости проверяют в изоляции
Подозрительные зависимости проверяют в изоляции

Главное не название формата. Важнее полнота данных и единые правила внутри компании. Команда заранее определяет обязательные поля для каждой записи.

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

SPDX удобно применять там, где важны сведения о компонентах и лицензиях. CycloneDX часто выбирают для описания состава приложения и зависимостей. На практике формат выбирают под инструменты сборки и обмена данными.

Не стоит создавать два списка вручную. Это приводит к расхождениям. Один формат можно сделать основным, а второй получать автоматически при необходимости.

Практический подход: закрепите один основной формат. Храните SBOM как часть артефакта выпуска и проверяйте его наличие до публикации.

Что сделать сейчас: опишите обязательные поля SBOM и добавьте проверку их заполнения в сборочный процесс.

🔐 Источник, хеш и цифровая подпись

Номер версии не подтверждает, что команда получила настоящий пакет. Злоумышленник может заменить архив. Он также может опубликовать пакет с похожим названием.

Проверка должна останавливать опасный релиз
Проверка должна останавливать опасный релиз

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

Хеш помогает проверить целостность файла. Система сравнивает вычисленное значение с ожидаемым. Несовпадение означает, что пакет изменился или пришёл не из того места.

Цифровая подпись даёт дополнительный сигнал о происхождении. Она не доказывает отсутствие вредоносного кода. Но подмена становится заметнее, если подпись отсутствует или не проходит проверку.

Lock-файл закрепляет выбранные версии. Он снижает риск неожиданного обновления при следующем запуске сборки. Однако сам lock-файл тоже защищают от несанкционированных изменений.

Проверяйте изменения в файлах зависимостей отдельно. Небольшое обновление может добавить новый пакет. Оно также может изменить сценарий установки.

Что сделать сейчас: блокируйте сборку при неизвестном источнике или несоответствии хеша.

🎯 Скрипты установки и подозрительные изменения

Пакет может запускать команды во время установки. Такие действия требуют отдельной проверки. Особенно внимательно смотрите на доступ к файлам, переменным среды и сети.

Подозрительным сигналом становится неожиданное обращение к внешнему узлу. Риск повышается, если пакет читает секреты или создаёт новые исполняемые файлы.

Проверяйте изменения между версиями. Сравнивайте исходный код, файлы сборки и сценарии установки. Отдельно отмечайте новые сетевые вызовы.

Автоматический анализ не заменяет просмотр изменений. Инструмент может показать новый файл, но не объяснить его назначение. Разработчик подтверждает, что изменение связано с задачей обновления.

Полезно собирать пакет в изолированной среде. Там проще увидеть попытки доступа к внешним ресурсам. Такая среда также ограничивает последствия ошибки.

Не предоставляйте сборке лишние секреты. Если процессу не нужен ключ, он не должен видеть ключ. Это правило снижает ущерб при компрометации зависимости.

Сигналы для ручной проверки: новый установочный скрипт, сетевой вызов, чтение секретов, скрытый исполняемый файл и резкое изменение состава пакета.

Что сделать сейчас: запускайте установку новых зависимостей в изолированной среде без рабочих секретов.

⚙️ Конвейер проверки до релиза

Контроль начинается с получения зависимостей. Система использует утверждённые источники и проверяет lock-файл. Затем она сверяет хеши и подписи.

Следующий шаг — сборка. Процесс должен быть воспроизводимым. Одинаковый исходный код и одинаковые версии должны давать сопоставимый результат.

После сборки создаётся SBOM. Он описывает фактический артефакт, а не только файлы проекта. Это важное различие. В итоговую поставку могут попасть дополнительные компоненты.

Затем система сопоставляет версии с базами OSV и NVD. Также проверяются рекомендации разработчиков компонентов. Результат связывается с конкретным выпуском.

После анализа применяются политики. Критическая уязвимость может остановить выпуск. То же правило действует для неподтверждённого источника и неверного хеша.

Последний шаг — публикация. В реестр попадает артефакт вместе с SBOM. Команда сохраняет результат проверок и решение о выпуске.

  1. Получите зависимости из разрешённого источника.
  2. Проверьте lock-файл, подписи и хеши.
  3. Соберите приложение в изолированной среде.
  4. Создайте SBOM по фактическому артефакту.
  5. Сверьте версии с OSV, NVD и рекомендациями разработчиков.
  6. Проверьте код, скрипты установки и сетевую активность.
  7. Примените политики и сохраните результаты.
  8. Выпустите продукт только после успешной проверки.

Что сделать сейчас: добавьте в конвейер отдельный этап, который останавливает выпуск при нарушении политики.

📊 Как использовать OSV, NVD и рекомендации разработчиков

Одна база не покрывает все задачи. OSV помогает сопоставлять версии пакетов с известными проблемами. NVD даёт дополнительное описание записей и условий применения.

Рекомендации разработчика компонента дополняют эти данные. В них могут быть сведения о затронутых версиях и доступном исправлении. Команда сверяет информацию перед блокировкой выпуска.

Нельзя автоматически считать каждую найденную запись критичной для продукта. Сначала проверьте версию. Затем определите, используется ли уязвимая функция.

Например, jackson-databind требует внимания при анализе Java-зависимостей. Для него указана CVE-2017-15095. Но решение зависит от конкретной версии и сценария работы приложения.

Результат проверки храните вместе с SBOM. Записывайте найденную запись, версию, решение и ответственного. Так команда понимает, почему выпуск разрешили или остановили.

Пересматривайте исключения. Временное разрешение не должно становиться постоянным. Для каждого исключения указывайте срок и условие закрытия.

Что сделать сейчас: объедините результаты OSV, NVD и рекомендаций разработчиков в одну карточку компонента.

🛡️ Проверка сборочной среды и секретов

Зависимость опасна не только внутри приложения. Она может воздействовать на сборочную среду. Поэтому права процесса сборки ограничивают заранее.

Сборка не должна иметь доступ ко всем внутренним системам. Ей нужны только необходимые файлы и разрешения. Секреты передаются на короткое время и не попадают в логи.

Контролируйте сетевые соединения. Для обычной сборки заранее определите допустимые направления. Неожиданный внешний запрос становится поводом для остановки и проверки.

Храните журналы установки и сборки. В них должны быть версии пакетов, источники и результаты проверок. Это помогает восстановить события после подозрительного изменения.

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

При анализе теневых ИИ-сервисов полезно искать признаки активации функции внутри обычной программы. Такой подход применим и к сборочным инструментам. Опасный компонент не всегда выглядит отдельным продуктом.

Что сделать сейчас: ограничьте права сборки и сохраните сетевые журналы установки зависимостей.

🔬 Что делать после выпуска

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

SBOM ускоряет такую проверку. Команда сопоставляет список компонентов с новыми сведениями. Если находится проблема, быстро определяется затронутый продукт.

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

При подозрении сохраняйте копию артефакта. Фиксируйте SBOM, хеши, журналы и результаты проверки. Не заменяйте спорный пакет до сохранения данных для анализа.

После исправления создайте новый SBOM. Старый перечень остаётся частью истории выпуска. Он помогает понять, какие версии находились в продукте раньше.

Минимальный цикл: создать SBOM, проверить зависимости, выпустить продукт, пересканировать его позже и сохранить историю изменений.

Что сделать сейчас: назначьте регулярное пересканирование всех выпущенных артефактов.

✅ Итоговый чек-лист перед публикацией

Команда готова к выпуску, когда видит полный состав продукта. В SBOM присутствуют прямые и транзитивные зависимости. Каждая запись связана с конкретной версией и артефактом.

Источники пакетов разрешены. Хеши совпадают. Lock-файл защищён. Подписи проверены там, где они доступны.

Проверка уязвимостей завершена. Результаты сопоставлены с OSV, NVD и рекомендациями разработчиков. Исключения имеют срок и понятное обоснование.

Скрипты установки просмотрены. Сетевые обращения объяснены. Сборка не получает лишние секреты. Журналы сохраняются.

  • SBOM создан по фактическому артефакту.
  • Транзитивные зависимости включены.
  • Источник каждого пакета известен.
  • Хеши и подписи прошли проверку.
  • Версии сопоставлены с актуальными базами.
  • Изменения в коде и скриптах просмотрены.
  • Сборка работает с ограниченными правами.
  • Критические нарушения блокируют выпуск.
  • SBOM сохраняется вместе с продуктом.
  • Для релиза назначено повторное сканирование.

SBOM делает цепочку поставки видимой. Но видимость не равна защите. Надёжный контроль соединяет перечень компонентов с проверкой происхождения, целостности и поведения.

Такой подход помогает отличать обычное обновление от опасного изменения. Он также сокращает время поиска затронутых продуктов. Главное — встроить проверку в каждый выпуск, а не выполнять её вручную после инцидента.

Что сделать сейчас: превратите этот список в обязательную политику выпуска и храните её результат вместе с SBOM.

📚 Читайте также

📖 Термины

CI/CD · Container Security · SBOM · SCA (Software Composition Analysis) · Supply Chain Attack

🔗 Источники