Supply Chain Security
SolarWinds (2020), Codecov (2021), 3CX (2023), xz-utils (2024) — атака на software supply chain сместилась с runtime на build и distribution. Я наблюдаю, что многие команды думают про безопасность цепочки поставок только в категории «прогнать сканер уязвимостей», а это лишь финальный слой. Настоящая защита — контролируемая цепочка артефактов с криптографически проверяемым provenance: signed commits → controlled build → SBOM → signed release → verify-on-deploy. Четвёртый лист под L1 Secure Development. Граница с Vulnerability Management чёткая: тот лист про реакцию на известные CVE, то есть на уже сломанное. Этот — про защиту самого процесса, где будущая уязвимость не успеет стать известной CVE, а приедет в прод через скомпрометированный конвейер.
Что должен уметь
Заголовок раздела «Что должен уметь»Главный навык на уровне L5 — проектировать конвейер под конкретные track, level и версию SLSA. В утверждённой спецификации v1.2 есть Build и Source tracks. Build L1 требует provenance, Build L2 — сборку на управляемой платформе и подписанный provenance, Build L3 — усиленную платформу сборки. Старая единая шкала SLSA 1–4 относится к спецификации до 1.0; говорить просто «SLSA Level 3» без track и version теперь недостаточно точно.
L4
- Понимает границы понятия
software supply chain: это не только внешние зависимости, а вся цепочка — репозиторий, раннер сборки, реестр артефактов, деплой, рантайм. - Применяет signed commits (GPG / Sigstore gitsign) и branch protection (signed-only merge в protected branches).
- Держит конвейер как код в репозитории, а не в веб-интерфейсе; секреты CI выдаёт через федерацию OIDC короткоживущими токенами, а не долгоживущими PAT. Шаги сборки закреплены по digest (
@sha256:...), а не по изменяемому тегу.
L5
- Проектирует конвейер под выбранный уровень SLSA Build и версию спецификации; отдельно учитывает требования Source track.
- Генерирует и публикует SBOM (Software Bill of Materials) — SPDX или CycloneDX, генерация в CI каждого артефакта (Syft / cdxgen), attestation подписан.
- Подписывает и проверяет артефакты: Sigstore cosign для образов и релизов, подпись без ключей через OIDC, политики допуска в Kubernetes, проверяющие подпись прямо на деплое.
- Защищается от подмены зависимостей и опечаточных пакетов: внутренние пакеты с зарезервированным пространством имён в публичном реестре, строгая конфигурация резолвера без отката с приватного на публичный, белый список во внутреннем зеркале.
L6+
- Внедряет программу на уровне организации: план по SLSA для каждого сервиса, централизованная инфраструктура подписи, проверка через политики как код, процедура оценки поставщиков, сопоставление с регуляторикой (EO 14028, EU CRA, NIST SSDF).
- Принимает стратегические решения: писать своё или брать чужое для критичных открытых зависимостей, что с этим делать по страховке, как планировать реагирование на компрометацию цепочки — в частности, какого масштаба отзыв и ротацию она за собой потянет.
Материалы
Заголовок раздела «Материалы»Книги и фреймворки
Заголовок раздела «Книги и фреймворки»- SLSA specification v1.2 (OpenSSF). Первичный источник для Build и Source tracks. При ссылке на level я бы всегда указывал track и version, чтобы требование можно было проверить.
- The Update Framework (TUF) (CNCF graduated). Спецификация безопасных систем обновления, устойчивая к компрометации ключа, компрометации реестра и повторной отправке старых обновлений. Лежит в основе Sigstore, Notary v2 и агента Datadog.
- in-toto framework. Спецификация свидетельств по всей цепочке поставок. SLSA использует их как формат.
- NIST SSDF (SP 800-218). Федеральные требования США к поставщикам ПО, появившиеся после указа EO 14028.
Статьи и доклады
Заголовок раздела «Статьи и доклады»- The xz-utils backdoor (CVE-2024-3094) — Andres Freund’s discovery. Главный публичный кейс — см. ниже.
- SolarWinds: рекомендации CISA пострадавшим сетям (Alert AA21-008A). Переломный инцидент: атакующие вошли через систему сборки и подписали вредоносное обновление легитимным сертификатом. Читать, чтобы понять, почему целостность среды сборки критична — и заодно чтобы оценить масштаб зачистки, которая требуется после такого класса компрометации.
- Codecov Bash Uploader Compromise. Компрометация конвейера через подменённый образ Docker: секреты из CI клиентов утекли наружу.
- Reproducible Builds. Движение и инструменты за побитовую воспроизводимость сборки — основа для проверяемых свидетельств о ней.
- OpenSSF Scorecard. Автоматическая оценка открытых репозиториев по практикам безопасности.
- The State of the Software Supply Chain (Sonatype, ежегодно). Отраслевые данные о вредоносных пакетах и сроках починки.
Инструменты
Заголовок раздела «Инструменты»- Signing & verification: Sigstore (cosign / fulcio / rekor — keyless signing через OIDC). По моим наблюдениям, к 2026-му это стандарт де-факто: он вытесняет долгоживущие ключи GPG. Notary v2, GPG (классика, для подписи коммитов), SSH commit signing (вариант поновее, проще GPG).
- SBOM generation: Syft (Anchore, генерация SPDX/CycloneDX), cdxgen (CycloneDX-native), Trivy (SBOM плюс скан уязвимостей), GitHub dependency graph.
- SLSA-compliant build: SLSA GitHub Generator, BuildKit с rootless mode, Tekton Chains, Google Cloud Build with provenance.
- Admission control (verify-on-deploy): Cosign Policy Controller, Kyverno (с verifyImages rule), OPA Gatekeeper, Connaisseur.
- Dependency management & hygiene: Renovate / Dependabot (автообновления с выдержкой), Socket.dev (анализ пакетов npm и PyPI на риск в реальном времени), Snyk, deps.dev.
- Registry security: Harbor (подписанные образы, проверка через Cosign, скан уязвимостей), JFrog Artifactory (Xray), GitHub Packages.
- Reproducible builds: Nix / NixOS, Bazel (герметичные сборки), Guix.
Best practices
Заголовок раздела «Best practices»Главный публичный кейс — xz-utils backdoor (CVE-2024-3094), обнаруженный Andres Freund в марте 2024. Атакующий под именем Jia Tan несколько лет вёл социальную инженерию против критичного открытого проекта, у которого был один сопровождающий: выстроил доверие, стал вторым мейнтейнером, постепенно протащил закладку в релизы. Нашли случайно. Freund заметил, что рукопожатие ssh на его личной машине стало есть заметно больше процессора, и пошёл разбираться. Главный урок: даже безупречный конвейер не спасёт от закладки наверху цепочки, если скомпрометирован сам этот верх. Защита лежит в гигиене зависимостей — не тащить в критичный путь библиотеку с единственным сопровождающим, смотреть на дату последнего коммита и на отзывчивость мейнтейнера, требовать нескольких сопровождающих там, где цена ошибки высока, и добиваться воспроизводимых сборок: закладка в xz работала именно потому, что сборка воспроизводимой не была.
Отсюда же граница применимости всей практики, и она узкая. Подписи, provenance и admission policies закрывают цепочку от вашего репозитория до кластера. Но подпись не спасает от того, что вы сами втянули в цепочку скомпрометированный upstream: это лечится гигиеной зависимостей, а не криптографией.
База, ниже которой опускаться незачем, — подписанные коммиты и подписанные релизы. Подпись коммита (GPG, SSH или Sigstore gitsign) с проверкой в branch protection закрывает целый класс атак через украденные учётки разработчика, подпись релиза даёт потребителю гарантию, что артефакт собрал легитимный процесс. Настраивается один раз на разработчика и один раз в CI.
Дальше — фиксация всего по digest, а не по тегу. FROM node:18, uses: actions/checkout@v4, pip install foo==1.2.3 без хеша: теги изменяемы, и атакующему достаточно опубликовать под тем же тегом другой образ. Digest неизменяем, а Renovate и Dependabot обновляют его сами, так что после автоматизации это стоит ноль.
И третье: проверять подпись на деплое, а не на сборке. Между build и deploy артефакт можно подменить — через компрометацию registry или MITM. Admission controller проверяет подпись в момент запуска, и неподписанный образ просто не стартует. Граница доверия проходит по deploy time.
Среда сборки — это поверхность атаки: одноразовые раннеры, федерация OIDC, никаких долгоживущих секретов. Раннер — машина с доступом ко всему сразу. Постоянный собственный раннер с вечным токеном в переменных окружения отдаёт атакующему все будущие сборки разом. Федерация OIDC выдаёт короткоживущий токен на конкретный запуск, привязанный к репозиторию, ветке и workflow, — украденный, он бесполезен где-либо ещё. Одноразовые раннеры (у GitHub из коробки, у себя — чистое состояние на каждую задачу) начинают каждую сборку с нуля. Это самый дешёвый и самый действенный сдвиг во всей теме.
SBOM — базовый артефакт: собирается на каждую сборку, подписывается, хранится. «Сгенерируем, когда аудит попросит» — это уже поздно. Через полгода после релиза выходит CVE, и единственный вопрос, на который нужно ответить за час, звучит так: в каких именно версиях наших артефактов лежал уязвимый пакет и куда они уехали. Без исторических SBOM ответа нет. Поэтому SBOM собирается в CI на каждый build (Syft, cdxgen), прикладывается к релизу и хранится не меньше года, в формате SPDX или CycloneDX.
Подмена зависимостей — реальный риск, лечится резервированием имён. Атака обидно простая. Внутренний пакет mycompany-utils живёт только во внутреннем реестре, публичный никто не проверял. Атакующий публикует mycompany-utils@99.0.0 в публичном npm или PyPI, и резолвер, у которого есть откат на публичный реестр, берёт именно его: версия-то выше. Защита — зарезервировать пространство имён в публичном реестре (@mycompany/utils), настроить резолвер строго (registry=https://internal/, никакого отката) либо держать белый список во внутреннем зеркале. Класс атак открыл Алекс Бирсан в феврале 2021: он выпустил пакеты с именами внутренних библиотек в публичные реестры и получил выполнение кода внутри Apple, Microsoft, PayPal, Shopify, Netflix, Tesla, Uber и ещё трёх десятков компаний, заработав на этом больше 130 тысяч долларов bug bounty. Обратите внимание, что от него не потребовалось ни одной уязвимости в обычном смысле слова — только имена внутренних пакетов, утёкшие в публичные артефакты.
Связанные листья
Заголовок раздела «Связанные листья»- Vulnerability Management — граница: тот лист реагирует на известные CVE, то есть на уже сломанное, этот защищает процесс, в котором будущая уязвимость не успеет стать CVE. Оба опираются на SBOM.
- Secrets Management — пересечение по федерации OIDC и по управлению ключами подписи. Централизованная инфраструктура подписи — та же дисциплина работы с секретами, только применённая к ключам.
- Threat Modeling — цепочка поставок — одна из границ доверия на схеме потоков данных. Track и level SLSA выбираются с оглядкой на модель угроз сервиса.
- CI/CD — конвейер и есть основная поверхность для компрометации цепочки. SLSA Build L2 требует, чтобы сборка шла на управляемой платформе.
- Progressive Delivery — политики допуска, проверяющие подпись на деплое, встроены в тот же конвейер выкатки.
- Infrastructure as Code — модули Terraform, чарты Helm и роли Ansible — та же цепочка поставок. Практики те же: подписанные релизы, закреплённые версии, SBOM.
- Incident Response — компрометация цепочки — особый класс инцидентов: огромный blast radius, а починка означает отзыв и ротацию всего, до чего атакующий мог дотянуться.
- Vendor Reliability — здесь на зависимости смотрят со стороны безопасности, там — со стороны надёжности; практики соседние и опираются на общий список поставщиков.
- Workload Identity — федерация OIDC в CI убирает долгоживущие учётные данные из сборки; связка «подписанный артефакт — identity того, кто его собрал» и есть часть цепочки SLSA.
- Compliance Frameworks — требования SOC 2 и ISO 27001 к рискам поставщиков плюс европейский Cyber Resilience Act — первое регуляторное требование с конкретикой по цепочке поставок. Регламент вступил в силу 10 декабря 2024, но основные обязанности производителей начинают действовать только с 11 декабря 2027, а требования по отчётности об уязвимостях — с сентября 2026. То есть время подготовиться формально есть, и именно поэтому большинство команд к нему ещё не приступало.
Открытые вопросы
Заголовок раздела «Открытые вопросы»Workload Identity и Compliance Frameworks отсюда уже уехали в отдельные листья, ссылки выше.
- Экономика bug bounty (TBD) — когда запускать, какие ставить границы, как устроены выплаты. Тот же вопрос уже висит в Vulnerability Management, так что это соседний лист, а не подраздел этого.
- Reproducible Builds (TBD) — линия Bazel, Nix и Guix; побитовый детерминизм; сложности, когда языков в проекте несколько. Может быть отдельным листом под Programming / Scripting; в SLSA v1.2 это не «Level 4».
Чего я не знаю — какой SLSA baseline разумно рекомендовать по умолчанию. Без threat model и требований к конкретному артефакту любая рекомендация превращается в карго-культ. Честнее фиксировать выбранные track + level + version вместе с обоснованием, чем объявлять один level нормой для всех.