SLSA и Supply Chain Security
Защита цепочки поставок ПО: SLSA framework, Sigstore и SBOM
SolarWinds, Log4Shell и 18 000 скомпрометированных организаций
В декабре 2020 года выяснилось, что атакующие пробрались в систему сборки SolarWinds Orion — популярной платформы для мониторинга сетей. Вредоносный код уехал в обновление, которое установили больше 18 000 организаций, включая госагентства США, Microsoft и Intel. Атака сидела незамеченной месяцами: обновление подписано валидным сертификатом SolarWinds, прошло все проверки целостности, ничто в нём не намекало на компрометацию.
Через год, в декабре 2021, всплыла уязвимость Log4Shell в Apache Log4j — одном из самых распространённых Java-компонентов для логирования. Можно было выполнить произвольный код, прислав специально сформированную строку в лог. Log4j использовался в миллионах приложений, и первые часы после раскрытия превратились в хаос: организации пытались понять, используют ли они эту библиотеку, в какой версии, через какие транзитивные зависимости. У кого был актуальный SBOM (Software Bill of Materials) — закрыли вопрос за часы. У остальных это заняло недели.
Эти два инцидента переписали разговор о безопасности цепочки поставок. Стало ясно: доверять подписанному артефакту мало — нужно доверять процессу его сборки. И знать свои зависимости — давно уже не опция.
SLSA: четыре уровня зрелости
SLSA (Supply-chain Levels for Software Artifacts, произносится «salsa») — фреймворк от Google и OpenSSF, который описывает прогрессивные уровни защиты цепочки поставок. Последняя версия — SLSA v1.1 от апреля 2025 года.
SLSA Level 1 — документация. Процесс сборки описан, для каждого артефакта генерируется provenance — машиночитаемый документ, фиксирующий, из какого исходного кода, каким инструментом и в каком окружении собран артефакт. На этом уровне provenance делает сам билд-процесс, доверие к нему опирается на доверие к мейнтейнеру.
SLSA Level 2 — подписанный provenance от hosted-сервиса. Provenance генерируется сервисом сборки (GitHub Actions, Google Cloud Build), а не скриптом разработчика. Сервис подписывает provenance, подтверждая, что сборка случилась на его инфраструктуре из указанного исходного кода.
SLSA Level 3 — изоляция сборки. Билд-процесс крутится в изолированном окружении, которое нельзя модифицировать ни разработчиком, ни другими процессами. Это закрывает сценарий SolarWinds, где атакующий модифицировал билд-сервер. На этом уровне даже скомпрометированный мейнтейнер не подменит артефакт незаметно.
SLSA Level 4 — двустороннее ревью и герметичные сборки. Каждое изменение проходит review от двух человек, сборка полностью воспроизводима и не зависит от внешних ресурсов. Самый строгий уровень, на практике его берут единицы — в основном критическая инфраструктура.
Фреймворк инкрементальный по задумке: старт с Level 1, дальше движение вверх по мере зрелости. В 2024 GitHub добавил встроенную поддержку attestations, и через slsa-github-generator SLSA Level 2 для большинства типов артефактов берётся за несколько часов работы.
Sigstore: подписание без управления ключами
Классическая боль подписания артефактов — управление ключами. Сгенерировать ключевую пару, держать приватный ключ в безопасности, ротировать, отзывать при компрометации, следить, чтобы у потребителей артефакта был актуальный публичный ключ. Для open-source проекта с тремя мейнтейнерами это уже обременительно.
Sigstore закрывает эту боль через keyless signing — подписание без долгоживущих ключей. Система состоит из трёх компонентов.
Fulcio — certificate authority, выпускающий короткоживущие сертификаты (срок действия — 10 минут). Сертификат выдаётся после аутентификации через OIDC: GitHub Actions, Google, Microsoft или другой OIDC-провайдер. Fulcio привязывает сертификат к identity (email или workflow) и к моменту времени.
Rekor — append-only transparency log, публичный и неизменяемый реестр всех подписаний. Подписал артефакт — запись уехала в Rekor. Любой может проверить, что конкретный артефакт подписан конкретной identity в конкретное время. Попытка подменить подпись будет видна в логе как расхождение.
Cosign — CLI для подписания и верификации. cosign sign подписывает Docker-образ, бинарник, SBOM или любой файл. cosign verify проверяет подпись. В CI-пайплайне (GitHub Actions) весь процесс автоматический: cosign получает OIDC-токен от GitHub, запрашивает сертификат у Fulcio, подписывает артефакт, пишет событие в Rekor — одной командой, без управления ключами.
SBOM: список ингредиентов вашего ПО
SBOM (Software Bill of Materials) — машиночитаемый документ, который перечисляет все компоненты приложения: прямые и транзитивные зависимости, версии, лицензии, известные уязвимости. Два основных формата — SPDX (от Linux Foundation) и CycloneDX (от OWASP).
После Log4Shell SBOM стал критическим элементом. CISA (Cybersecurity and Infrastructure Security Agency) сделал его одним из краеугольных элементов своих рекомендаций по безопасности: когда выйдет следующий Log4Shell, организации с актуальными SBOM определят затронутые системы за часы, а не за недели.
Генерация SBOM встроена в современные инструменты. Syft от Anchore сканирует Docker-образы и файловые системы, npm sbom собирает SBOM для Node.js-проектов, Trivy от Aqua Security совмещает генерацию SBOM со сканированием уязвимостей. Cosign умеет подписывать SBOM и прикреплять подписанный SBOM к Docker-образу, создавая верифицируемую связь между образом и списком его компонентов.
npm, PyPI и проблема доверия к пакетам
К 2024 году supply chain атаки на пакетные менеджеры выросли на 1300% за три года. Typosquatting (регистрация пакета с похожим именем — crypt0graphy вместо cryptography), dependency confusion (публикация пакета с именем внутреннего пакета компании в публичном реестре), захват заброшенных пакетов — атаки становятся изощрённее.
В 2025 году кампания MUT-8694 одновременно била по npm и PyPI, распространяя infostealer через пакеты, маскирующиеся под популярные утилиты. В июне 2025 атака на экосистему GlueStack зацепила больше дюжины пакетов с суммарным количеством загрузок около миллиона в неделю.
Защита тут многослойная. npm audit и pip-audit проверяют известные уязвимости в зависимостях — добавьте их в CI. Lock-файлы (package-lock.json, poetry.lock) фиксируют точные версии и хэши зависимостей — коммитьте их и проверяйте целостность при установке (npm ci вместо npm install). Socket.dev анализирует поведение пакетов: если после обновления пакет полез в сеть или в файловую систему, Socket это поймает. Дополнительно сканеры SAST и DAST помогут заметить подозрительное поведение уже на уровне вашего кода.
Для внутренних пакетов используйте scoped registries: npm/pip настраиваются так, что пакеты с конкретным scope (@mycompany/) тянутся только из приватного registry, а не из публичного. Это закрывает вектор dependency confusion.
Практический маршрут
Внедрение supply chain security — как и SLSA — задумано инкрементальным. Вот четыре шага от «ничего нет» до разумного уровня защиты.
Шаг 1 — включить npm audit / pip-audit / trivy в CI в духе shift-left. Пайплайн падает на критических уязвимостях в зависимостях. 20 минут настройки и SLSA Level 0, но сценарий «используем библиотеку с известной CVE и не в курсе» закрыт.
Шаг 2 — добавить генерацию SBOM в release pipeline. Syft или встроенный npm sbom собирает документ, который сохраняется рядом с артефактом. Выйдет следующий Log4Shell — SBOM откроется и за 5 минут даст ответ, задело или нет.
Шаг 3 — подписать артефакты через Cosign. Для GitHub Actions есть slsa-github-generator: даёт SLSA Level 2 provenance с минимальной настройкой, в документации GitHub лежит пошаговый гайд для Go-модулей, контейнеров и generic-артефактов.
Шаг 4 — настроить верификацию при деплое. Kubernetes admission controller (Kyverno или OPA Gatekeeper) проверит, что деплоящийся образ подписан вашим CI и имеет валидный provenance. Цепочка замыкается: код прошёл ревью → CI собрал и подписал → Kubernetes проверил подпись → образ поднялся в production.