Навигация

Безопасность зависимостей и supply chain

Современный фронтенд-проект имеет сотни, а иногда и тысячи транзитивных зависимостей. Каждая из них — чужой код, который выполняется в вашем приложении. История последних лет — от event-stream до xz utils — показала, что supply chain-атаки реальны и разрушительны. Статья систематизирует векторы атак (компрометация мейнтейнера, typosquatting, вредоносные новые версии), инструменты защиты (npm audit, Snyk, Socket, Dependabot, Renovate), lock-файлы, SBOM, provenance и приватные registry.

Содержание

  1. Что такое supply chain attack
  2. Как зависимости становятся угрозой
  3. Известные инциденты
  4. npm audit и аналоги
  5. Lock-файлы: почему они важны
  6. Snyk, Socket и другие инструменты
  7. SBOM: Software Bill of Materials
  8. Provenance и reproducible builds
  9. Приватные registry и ограничение источников
  10. Чек-лист безопасности зависимостей
  11. Терминология
  12. Ключевые тезисы для интервью
  13. Заключение
  14. Полезные ссылки

Что такое supply chain attack

Supply chain attack — это атака на цепочку поставок ПО. Злоумышленник не ломает ваше приложение напрямую. Вместо этого он внедряет вредоносный код в один из компонентов, которые вы используете: npm-пакет, библиотеку, инструмент сборки, образ Docker, GitHub Action.

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

В современном фронтенде supply chain особенно уязвима: проект среднего размера легко имеет сотни и тысячи транзитивных зависимостей.


Как зависимости становятся угрозой

Компрометация аккаунта мейнтейнера

Если у разработчика пакета украли пароль от npm, злоумышленник может опубликовать вредоносную версию от его имени.

Тайком переданный доступ

Мейнтейнер устал поддерживать пакет и передал права незнакомцу, который оказался злоумышленником.

Вредоносный код в новой версии

Легитимный мейнтейнер внезапно добавляет в пакет майнер, шифровальщик или скрипт для кражи данных.

Транзитивные зависимости

Вы устанавливаете пакет A, который зависит от B, который зависит от C. C может быть вредоносным, даже если A и B чистые.

typosquatting

Пакеты с именами, похожими на популярные: loadsh вместо lodash, react-domm вместо react-dom. Разработчик ошибается при установке и получает вредонос.


Известные инциденты

ua-parser-js (2021)

Популярный пакет для определения User-Agent. Аккаунт мейнтейнера был скомпрометирован, в версии был добавлен вредоносный код, который скачивал майнер и трояна. Пакет скачивали более 13 миллионов раз в неделю.

colors (2022)

Мейнтейнер намеренно внес бесконечный цикл и странный вывод в пакет colors и faker в знак протеста против коммерческого использования. Это не была кража данных, но показала, насколько хрупок supply chain.

event-stream (2018)

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

xz utils (2024)

Хотя это не JavaScript, это один из самых громких supply chain инцидентов. В популярную библиотеку сжатия был внедрён бэкдор на уровне build-скриптов. Показал, что угроза реальна для любого ПО.


npm audit и аналоги

Все основные пакетные менеджеры имеют встроенный аудит:

# npm
npm audit
npm audit --audit-level=high

# pnpm
pnpm audit

# yarn
yarn audit

Эти команды сравнивают ваши зависимости с базой данных известных уязвимостей (основанной на GitHub Advisories) и показывают:

  • уровень серьёзности;
  • CVE-идентификатор;
  • затронутые версии;
  • рекомендации по исправлению.

Автоматизация в CI/CD

# .github/workflows/security.yml
name: Security Audit
on: [push, pull_request]
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm audit --audit-level=high

Если audit находит уязвимости уровня high/critical, CI падает и PR не мержится.

Ограничения npm audit

  • Проверяет только известные CVE.
  • Не анализирует поведение пакета (нет ли шпионского кода без CVE).
  • Может давать ложные срабатывания.

Lock-файлы: почему они важны

package-lock.json, pnpm-lock.yaml, yarn.lock фиксируют точные версии всех зависимостей, включая транзитивные.

Почему это важно для безопасности

Без lock-файла npm install может установить более новую версию зависимости, чем та, которую вы тестировали. Если злоумышленник опубликует вредоносную версию, она попадёт в сборку.

Lock-файл гарантирует, что на всех окружениях (dev, CI, production) устанавливаются одинаковые версии.

Правила

  • Всегда коммитьте lock-файлы.
  • Используйте npm ci / pnpm install --frozen-lockfile в CI/CD.
  • Регулярно обновляйте зависимости осознанно, а не случайно.

Snyk, Socket и другие инструменты

Snyk

  • Сканирует зависимости на известные уязвимости.
  • Может автоматически создавать PR с обновлениями.
  • Поддерживает SCA (Software Composition Analysis).
  • Есть бесплатный тариф для open-source.

Socket

Анализирует не только CVE, но и поведение пакетов:

  • обращается ли пакет к сети;
  • читает ли файлы за пределами своей директории;
  • использует ли obfuscation;
  • добавляет ли shell-скрипты в install-хуки.

Socket помогает находить угрозы, у которых ещё нет CVE.

Dependabot

Встроен в GitHub. Автоматически создаёт PR для обновления зависимостей с известными уязвимостями.

Renovate

Альтернатива Dependabot с бóльшим количеством настроек и поддержкой монорепозиториев.

npm/package签名

С 2024 года npm активно продвигает provenance и подпись пакетов. Подписанные пакеты позволяют проверить, что пакет был собран из конкретного исходного кода на доверенной платформе.


SBOM: Software Bill of Materials

SBOM — это «ингредиенты» вашего приложения: полный список всех зависимостей и их версий.

Форматы

  • SPDX — стандарт Linux Foundation.
  • CycloneDX — популярен в безопасности.

Генерация

# npm
npm sbom --sbom-format=spdx-json

# cyclonedx
npx @cyclonedx/cyclonedx-npm --output-file=sbom.json

Зачем нужен

  • Быстро ответить на вопрос «затронуты ли мы уязвимостью X?».
  • Передавать заказчикам и аудиторам.
  • Соответствовать требованиям SOC2, NIST, EO 14028.

Provenance и reproducible builds

Provenance

Provenance (происхождение) — это метаданные, подтверждающие, что пакет был собран из конкретного коммита в конкретном репозитории на доверенной CI-платформе.

npm поддерживает provenance для пакетов, опубликованных через GitHub Actions. Это позволяет пользователям проверить:

  • откуда взялся пакет;
  • кто его собрал;
  • не был ли он подменён.
npm publish --provenance

Reproducible builds

Reproducible build — это сборка, которая даёт идентичный результат при повторном запуске. Если сборка воспроизводима, легче обнаружить, что кто-то подменил артефакты.

В JavaScript-мире полностью воспроизводимые сборки сложны, но lock-файлы и фиксированные версии инструментов — первый шаг.


Приватные registry и ограничение источников

Приватный registry

Крупные компании используют приватные npm-регистри (Verdaccio, Nexus, Artifactory), чтобы:

  • контролировать, какие пакеты доступны;
  • кэшировать внешние пакеты;
  • публиковать внутренние пакеты;
  • сканировать пакеты перед использованием.

.npmrc

# Разрешаем устанавливать только из доверенных источников
registry=https://registry.npmjs.org/
@mycompany:registry=https://npm.mycompany.com/

Ограничение пакетов

Некоторые инструменты позволяют запретить установку пакетов по критериям:

  • возраст пакета;
  • количество мейнтейнеров;
  • наличие скриптов postinstall;
  • наличие зависимостей от заблокированных пакетов.

Чек-лист безопасности зависимостей

Регулярно

  • Запускать npm audit / pnpm audit.
  • Обновлять зависимости через Dependabot/Renovate.
  • Просматривать security advisories для ключевых фреймворков.

В процессах

  • Коммитить lock-файлы.
  • Использовать npm ci / --frozen-lockfile в CI.
  • Настроить CI-проверку npm audit --audit-level=high.
  • Использовать Snyk, Socket или аналог для мониторинга.

При добавлении новых зависимостей

  • Проверить популярность, возраст и активность пакета.
  • Посмотреть исходный код, если пакет маленький.
  • Проверить, есть ли скрипты postinstall.
  • Избегать typosquatting — проверять имя пакета.

Для compliance

  • Генерировать SBOM.
  • Использовать пакеты с provenance, где возможно.
  • Вести реестр одобренных зависимостей.

Терминология

ТерминЗначение
Supply chain attackАтака через цепочку поставок ПО
Transitive dependencyЗависимость зависимости
CVECommon Vulnerabilities and Exposures — идентификатор уязвимости
SCASoftware Composition Analysis — анализ состава ПО
Lock-fileФайл с фиксированными версиями зависимостей
SBOMSoftware Bill of Materials — список компонентов ПО
ProvenanceДоказательство происхождения пакета
Reproducible buildСборка, дающая идентичный результат
TyposquattingРегистрация имён, похожих на популярные пакеты
Postinstall scriptСкрипт, выполняемый при установке пакета

Ключевые тезисы для интервью

  • Supply chain attack — внедрение вредоносного кода через компонент цепочки (npm-пакет, GitHub Action, Docker-образ); векторы: компрометация мейнтейнера, typosquatting, вредоносные новые версии, транзитивные зависимости.
  • Реальные инциденты (ua-parser-js, event-stream, colors, xz utils) показали, что даже мейнтейнер доверенного пакета может стать угрозой.
  • npm audit проверяет известные CVE через GitHub Advisories; Socket анализирует поведение пакетов (сеть, файлы, obfuscation, postinstall) и находит угрозы без CVE.
  • Lock-файлы фиксируют точные версии; npm ci/--frozen-lockfile в CI гарантирует воспроизводимость; SBOM (SPDX, CycloneDX) — список ингредиентов для быстрого ответа на уязвимости.
  • Provenance подтверждает, что пакет собран из конкретного коммита на доверенной CI (npm publish --provenance); приватные registry (Verdaccio, Nexus) позволяют кэшировать, сканировать и ограничивать источники.
  • При добавлении зависимости проверяйте: возраст, популярность, активность мейнтейнеров, postinstall-хуки, имя (typosquatting).

Заключение

Supply chain — один из самых серьёзных рисков современного фронтенда. Вы не контролируете все тысячи строк кода в node_modules, но можете контролировать процессы: регулярный аудит, lock-файлы, сканирование через Snyk/Socket, ограничение источников через приватные registry. Инциденты последних лет — от event-stream до xz utils — показали, что даже мейнтейнер годами доверенного пакета может стать угрозой. Для SOC2 и CASA важно показать регулярный аудит зависимостей, процесс реагирования на уязвимости, использование SBOM и контроль над поставщиками ПО. Установка npm-пакета — не безобидное действие, а принятие чужого кода в свой проект.

Полезные ссылки