Как оценивать новую зависимость до merge: короткий due diligence для команды
Dependency появляется в PR — и вместе с ней появляется риск. Вот как его оценить за несколько минут, не утонув в бесконечных проверках.
Введение: зависимость — это не просто строка в package.json
Когда разработчик или AI-ассистент добавляет в pull request новую зависимость, это кажется тривиальным. Строка в package.json, requirements.txt или go.mod — что может пойти не так?
На самом деле — многое. Средняя enterprise-разработка содержит около 180 открытых компонентов [2]. Каждый из них — это неявное доверие к цепочке: реестру, мейнтейнерам, их инфраструктуре сборки, аккаунтам в CI/CD. Один скомпрометированный узел в этой цепочке — и атакующий получает прямой доступ к вашей кодовой базе.
В 2024 году число вредоносных OSS-пакетов выросло на 156% год к году [2]. XZ Utils и LUMMA в PyPI показали, что атаки становятся всё более изощрёнными и обходят традиционные средства защиты [2]. Появился новый класс угрозы — slopsquatting: AI-ассистент предлагает несуществующий пакет, атакующий регистрирует это имя, разработчик устанавливает вредонос [3].
Это не повод впадать в паранойю. Это повод выработать короткий, воспроизводимый due diligence, который команда может выполнить за несколько минут при каждом добавлении зависимости.
Почему существующих автоматических проверок недостаточно
npm audit, pip-audit, osv-scanner, Dependabot — всё это важные инструменты. Они проверяют известные уязвимости и делают это надёжно. Но у них есть общее ограничение: они работают с тем, что уже известно.
npm audit обнаруживает только уязвимости, которые уже задокументированы и проиндексированы [13]. Он не видит свежеопубликованный вредоносный пакет, который ещё не попал в базу. Он не оценивает, брошен ли проект мейнтейнером два года назад. Он не знает, прошла ли публикация через доверенную CI-систему или через скомпрометированный токен.
Кроме того, 92% публично доступных данных об уязвимостях требуют корректировки версий после детального исследования [2]. Это означает, что автоматика часто работает с неточными данными.
Due diligence — это не замена автоматических сканеров. Это дополнительный слой: несколько структурированных вопросов, которые помогают принять решение до merge.
Семь сигналов: короткий due diligence до merge
1. Existence in registry: этот пакет вообще существует?
Первый вопрос звучит тривиально, но он критически важен в эпоху AI-кодинга.
Исследование USENIX Security 2025 протестировало 16 LLM на 576 000 примерах кода. Результат: около 20% рекомендованных пакетов не существовало в реестре [3]. Это явление получило название slopsquatting — атакующий регистрирует имя, которое AI регулярно галлюцинирует. Исследователь Bar Lanyado зарегистрировал huggingface-cli на PyPI и получил более 30 000 загрузок за три месяца, включая ссылки в документации крупных компаний [3, 4].
Что проверять:
- Найти пакет напрямую в реестре (npmjs.com, pypi.org, crates.io, pkg.go.dev и т.д.)
- Убедиться, что имя точно совпадает с тем, что в PR — без лишних символов, дефисов, цифр
- Сравнить имя с популярными пакетами из той же области: typosquatting (
lodahsвместоlodash) и dependency confusion (публичный пакет с именем внутреннего) — старые, но живые атаки [1, 3] - Если пакет предложил AI-ассистент, проверить его существование перед установкой, а не после
2. Advisories: есть ли известные уязвимости?
Второй сигнал — быстрая проверка по базам уязвимостей.
Основные источники:
- GitHub Advisory Database — более 20 000 рецензированных advisory по состоянию на 2024 год, в формате OSV [5]
- osv.dev (Google) — агрегатор, объединяющий GitHub Advisory, RustSec, PyPA, NVD и другие источники, с удобным API [6]
- OSV-Scanner — CLI-инструмент от Google, умеет сканировать lockfile-ы и интегрироваться в GitHub Actions для проверки новых зависимостей в PR [6]
- Для Python:
pip-auditи Safety CLI [7] - Для Rust:
cargo-audit[8]
Ключевое правило: проверять не только прямую зависимость, но и её транзитивные зависимости. Уязвимость в urllib3 (CVE-2024-37891) затронула 2 169 гарантированно зависимых пакетов [9]. Транзитивные зависимости приезжают незаметно, но несут ровно тот же риск.
Если обнаружена CVE: проверить, существует ли исправленная версия. По данным Sonatype, в 95% случаев при потреблении уязвимого компонента исправленная версия уже доступна [2]. Потребление уязвимой версии при наличии патча — это комплаенс-риск и технический долг одновременно.
3. Package age: как давно пакет существует?
Возраст пакета — неочевидный, но важный сигнал.
71.2% вредоносных пакетов в npm используют длинные имена (более 10 символов), 67.3% содержат дефисы, имитируя легитимные соглашения об именовании [1]. Новый пакет с нулевой историей и именем, похожим на популярную библиотеку — красный флаг.
Что смотреть:
- Дата первой публикации в реестре (присутствует на странице пакета на npmjs.com и pypi.org)
- История версий: было ли нормальное, постепенное развитие, или пакет появился недавно с сразу "зрелым" API?
- Соотношение числа загрузок к возрасту: аномально высокое число загрузок у нового пакета может указывать на star-jacking — клонирование популярного репозитория для создания ложного кредита доверия [1]
Datadog GuardDog дополнительно проверяет email-домен мейнтейнера: если домен был перерегистрирован после последнего релиза пакета, это может указывать на захват аккаунта [10].
4. Maintenance: кто и как поддерживает пакет?
Pуброшенный проект — это медленно накапливающийся риск. Если мейнтейнер перестал следить за пакетом, уязвимости в нём не будут исправляться, а зависимость от него будет тянуть за собой ограничения по обновлению.
Сигналы хорошего состояния:
- Последний коммит и релиз — не позднее 12 месяцев назад
- Открытые issues и PR получают ответы
- Есть задокументированная security policy (файл
SECURITY.md) - Более одного активного контрибьютора (single-maintainer риск)
По данным Sonatype, проекты с платной поддержкой в три раза чаще имеют comprehensive security policy и закрывают уязвимости на 45% быстрее [2]. Это не означает, что нужно избегать community-проектов — но это сигнал к повышенному вниманию.
Для оценки можно использовать данные CHAOSS Community или просто посмотреть на GitHub Insights: частоту коммитов, количество разных контрибьюторов за последний год, время реакции на issues.
5. Project health: OpenSSF Scorecard
OpenSSF Scorecard — это автоматизированный инструмент от Open Source Security Foundation, который оценивает проекты по набору метрик безопасности [11, 12]. Запущен в ноябре 2020 года совместно с Google, он стал стандартом де-факто для оценки здоровья OSS-проекта.
Scorecard проверяет:
- Наличие code review перед merge
- Branch protection
- Использование инструментов автоматического обновления зависимостей (Dependabot, Renovate)
- Наличие CI/CD тестирования
- Отсутствие binary artifacts в репозитории
- Security policy
- Dangerous workflows в GitHub Actions
Результат — числовой score от 0 до 10 с расшифровкой по каждому критерию 12]. Проверить пакет можно на [scorecard.dev или через CLI:
scorecard --repo=github.com/owner/repo
Scorecard также интегрируется в PR через GitHub Actions, автоматически оценивая новые зависимости при их добавлении [11].
Важная оговорка: Scorecard оценивает процессы и инфраструктуру проекта, но не само содержание кода. Высокий балл снижает вероятность небрежности, но не гарантирует отсутствие уязвимостей.
6. Trusted publishing: как публикуется пакет?
Традиционная схема публикации в npm или PyPI предполагала долгоживущие API-токены у мейнтейнера. Компрометация токена = возможность публикации вредоносной версии. Именно так произошёл ряд атак захвата аккаунтов [13].
Trusted Publishing — это механизм, при котором пакет публикуется не через токен, а через OIDC-идентификацию CI/CD-платформы (GitHub Actions, GitLab CI). Платформа выступает доверенным издателем, долгоживущий токен не нужен [14].
Состояние по экосистемам:
- npm: Trusted Publishing достиг GA в июле 2025 года; при публикации через него автоматически прикрепляется provenance-аттестация [15]
- PyPI: Trusted Publishing доступен через GitHub Actions и GitLab CI с 2023 года; PEP 740 добавил поддержку SLSA provenance [14]
- crates.io: Trusted Publishing — GA с июля 2025 года (GitHub Actions), GitLab CI — с января 2026 года [15]
Как проверить: на странице пакета на npmjs.com или pypi.org обычно отображается информация о том, через какой publisher прошёл последний релиз. Отсутствие Trusted Publishing не означает автоматически, что пакет опасен, — но его наличие даёт дополнительную уверенность в целостности цепочки сборки.
7. Provenance: можно ли верифицировать происхождение?
Provenance — это криптографически верифицируемые метаданные о том, как именно был собран и опубликован пакет: из какого репозитория, в каком коммите, через какой CI-пайплайн [16].
Стандарт SLSA (Supply-chain Levels for Software Artifacts) определяет три уровня:
- Level 1: provenance-файл опубликован и доступен
- Level 2: файл подписан build-платформой, сборка выполнялась на dedicated-инфраструктуре
- Level 3: дополнительное hardening — signing key недоступен пользовательским шагам, сборки изолированы друг от друга [16]
Сигнатуры строятся на базе Sigstore (Fulcio + Rekor). Rekor — публичный transparency log, в котором отражается каждое подписанное событие [17].
Как это помогает: если атакующий скомпрометировал аккаунт мейнтейнера и опубликовал вредоносную версию, он не сможет сгенерировать валидную provenance-аттестацию без одновременной компрометации CI-инфраструктуры [16]. Это не абсолютная защита, но существенно повышает стоимость атаки.
Текущая реальность: принятие provenance остаётся неравномерным. Даже для проекта Sigstore лишь 7.2% npm-зависимостей имеют provenance-аттестации. PyPI демонстрирует более быстрое принятие — до 32.7% зависимостей для некоторых проектов [15]. Отсутствие provenance у старого, хорошо известного пакета — не повод для отказа; его отсутствие у нового или малоизвестного пакета — сигнал к осторожности.
Проверить provenance для npm-пакета можно через:
npm install --audit signatures <package-name>
Или напрямую через API реестра:
curl -s 'https://registry.npmjs.org/-/npm/v1/attestations/<package>@<version>' | jq '.attestations[].predicateType'
Decision framework: что делать с результатами
Семь сигналов дают картину, но нужен принцип принятия решения.
Жёсткие блокеры (merge не допускается):
- Пакет не найден в официальном реестре или имя подозрительно похоже на другой пакет
- Активная CVE с высоким или критическим CVSS, для которой нет исправленной версии
- Признаки вредоносного поведения (install-скрипты, отправляющие данные, обфусцированный код)
- Пакет опубликован несколько дней назад, не имеет истории, имитирует популярную библиотеку
Жёлтые флаги (требуют дополнительного обсуждения):
- CVE существует, но исправленная версия доступна — использовать исправленную версию
- Проект не обновлялся более года — оценить критичность зависимости и альтернативы
- Single-maintainer без security policy — добавить мониторинг через Dependabot/Renovate
- Нет Trusted Publishing или provenance — задокументировать и принять осознанное решение
Зелёный свет (можно merge):
- Пакет существует, имеет историю, имя уникально
- Нет активных CVE или используется исправленная версия
- OpenSSF Scorecard >= 7, активное поддержание
- Trusted Publishing или provenance присутствуют
Ошибки, которые совершают команды
"Мы доверяем популярным пакетам". Популярность снижает вероятность мошенничества, но не исключает взлом аккаунта мейнтейнера. Атаки на ua-parser-js, coa, rc в 2021 году показали, что популярный пакет — это привлекательная цель [1].
"AI написал этот import, значит всё в порядке". LLM галлюцинируют пакеты с частотой 5–21% в зависимости от модели [3]. Коммерческие модели типа GPT — около 5.2%, открытые модели — до 21.7% [3]. "Принять всё" в vibe coding без проверки — прямой путь к slopsquatting.
"Мы используем npm audit, этого достаточно". npm audit не видит свежеопубликованный вредоносный пакет, не оценивает здоровье проекта и не проверяет provenance [13]. Это необходимый, но не достаточный инструмент.
"Мы проверили при добавлении, теперь не нужно". 80% enterprise-зависимостей не обновляются больше года [2]. Состояние пакета меняется: мейнтейнер уходит, появляется CVE, проект форкается. Due diligence при добавлении — это не разовое событие, а начало мониторинга.
"Транзитивные зависимости — не наша проблема". 70–90% кодовой базы — сторонние компоненты, большинство из которых транзитивные [4]. Уязвимость в глубоко вложенной зависимости всё равно попадает в ваш продукт.
Инструменты в одном месте
Для удобства: ключевые инструменты, которые покрывают разные аспекты due diligence.
Проверка advisories:
osv-scanner— мультиэкосистемный, интегрируется в CI [6]pip-audit— Python-специфичный, интегрируется с GitHub Actions [7]cargo-audit— для Rust [8]- Dependabot / Renovate — автоматический мониторинг после merge
Project health:
- scorecard.dev — OpenSSF Scorecard онлайн [12]
scorecardCLI — для локального запуска и интеграции в PR [11]
Provenance:
- deps.dev (Google) — показывает provenance для npm и PyPI [17]
npm install --audit signatures— верификация npm provenance [15]gh-verifyCLI — проверяет SLSA/провenance для репозитория [15]
Комплексное сканирование:
- socket.dev — анализирует diff зависимостей при PR, выявляет malware [4]
- GuardDog (Datadog) — статический анализ Python-пакетов [10]
Как встроить это в процесс команды
Due diligence эффективен, когда он встроен в workflow, а не выполняется по требованию.
В PR-шаблоне добавить чек-лист: "Если в PR есть новые зависимости — проверены ли existence, advisories, project health?" Это занимает 2–3 минуты, но создаёт привычку.
В CI/CD настроить автоматические проверки:
- OSV-Scanner для сканирования новых зависимостей в PR
- OpenSSF Scorecard Action для оценки проектов
- npm provenance verification или эквивалент для вашего экосистема
В code review — ревьюер не обязан проверять все семь сигналов вручную, если автоматика уже отработала базовые. Задача ревьюера — интерпретировать результат в контексте конкретного PR.
Именно здесь возникает разрыв, который становится острее по мере роста скорости AI-кодинга: PR появляются быстрее, дифы длиннее, новые зависимости приезжают как побочный эффект AI-сгенерированного кода. Ревьюер физически не успевает дочитать lockfile до конца.
HighVibe закрывает этот разрыв как слой контроля между CI и merge: он анализирует конкретное изменение — включая новые и обновлённые зависимости — и даёт команде короткий, понятный сигнал: что изменилось, какой риск это несёт и что делать дальше. Не ещё один длинный отчёт, а оперативный ответ на вопрос "можно ли безопасно принять именно этот PR сейчас".
Кейс: как небольшой контекст меняет решение
Рассмотрим сценарий: PR добавляет зависимость fast-xml-parser@4.4.0 для нового парсера конфигурации.
Быстрая проверка по семи сигналам:
- Existence: пакет существует на npmjs.com, имя уникально — ок
- Advisories: CVE-2023-34104 и CVE-2024-41818 — ReDoS-уязвимости; версия 4.4.0 вышла после патча — ок
- Package age: пакет существует с 2016 года, активная история версий — ок
- Maintenance: последний коммит — месяц назад, активное community — ок
- OpenSSF Scorecard: 6.8 — приемлемо, есть code review, но нет dependency pinning
- Trusted Publishing: не настроен
- Provenance: отсутствует для версии 4.4.0
Итог: жёлтый флаг по Scorecard и отсутствию Trusted Publishing. Для библиотеки парсинга конфигурации, которая будет работать с user input, это стоит зафиксировать. Решение: принять, добавить мониторинг через Dependabot, задокументировать в SBOM.
Тот же процесс для нового пакета, опубликованного неделю назад, с именем fast-xml-parzer дал бы однозначный стоп уже на первом сигнале.
Будущее: регуляторное давление и автоматизация
Контекст регулирования меняется. NIS2 вступила в силу в октябре 2024 года и напрямую затрагивает управление supply chain security для операторов критической инфраструктуры [2]. NIST SP 800-53 Release 5.2.0 (август 2025) добавил 14 новых контролей, касающихся supply chain security [2]. EU Cyber Resilience Act вводит требования к безопасности продуктов с цифровыми элементами.
SBOM становится не best practice, а обязательством: Executive Order 14028 в США, CRA в ЕС — оба явно упоминают SBOM как инструмент прозрачности [2]. Организации, которые выстраивают процессы сейчас, будут в лучшей позиции, когда требования станут жёсткими.
Одновременно растёт автоматизация проверок. OSS Rebuild от Google уже генерирует SLSA Level 3 provenance для тысяч пакетов в npm, PyPI и crates.io [18]. Это означает, что всё большая доля экосистемы будет верифицируема криптографически — и инструменты, которые команды используют сегодня, станут точнее и полнее.
Заключение: несколько минут vs. цена инцидента
Due diligence новой зависимости — это инвестиция примерно в 5–10 минут до merge. Инцидент supply chain attack, в среднем, обнаруживается за 267 дней и обходится в $4.91 млн [2].
Семь сигналов — existence, advisories, package age, maintenance, OpenSSF Scorecard, trusted publishing, provenance — не требуют специальных знаний безопасности. Они требуют привычки. Встроите эту привычку в шаблон PR — и большинство рисков будет пойманы до того, как они попадут в main.
AI-кодинг ускоряет появление зависимостей. Это не проблема — это контекст, в котором нужно работать. Ответ на него — не замедление, а автоматизация контроля. Инструменты есть. Стандарты есть. Осталось встроить их в процесс.
Источники
[1] Socket.dev — The Landscape of Malicious Open Source Packages: 2025 Mid-Year Threat Report — https://socket.dev/blog/malicious-open-source-packages-2025-mid-year-threat-report
[2] Sonatype — 10th Annual State of the Software Supply Chain Report 2024 — https://www.sonatype.com/state-of-the-software-supply-chain/2024/introduction
[3] Research Square — AI-Induced Supply-Chain Compromise: A Systematic Review of Package Hallucinations and Slopsquatting Attacks (2025) — https://www.researchsquare.com/article/rs-8007192/v1
[4] Pixelmojo — Slopsquatting and AI Supply Chain Attacks: A Defense Guide — https://www.pixelmojo.io/blogs/slopsquatting-ai-supply-chain-attacks-defense-guide
[5] GitHub Blog — GitHub Advisory Database by the Numbers — https://github.blog/security/github-advisory-database-by-the-numbers-known-security-vulnerabilities-and-what-you-can-do-about-them/
[6] Google — OSV.dev: Open Source Vulnerabilities — https://osv.dev
[7] PyPA — advisory-database for Python packages — https://github.com/pypa/advisory-database
[8] RustSec — advisory-db for Rust crates — https://github.com/rustsec/advisory-db
[9] arXiv — PyPitfall: Dependency Chaos and Software Supply Chain Vulnerabilities in Python (2025) — https://arxiv.org/html/2507.18075v1
[10] Datadog Security Labs — Finding malicious PyPI packages through static code analysis: GuardDog — https://securitylabs.datadoghq.com/articles/guarddog-identify-malicious-pypi-packages/
[11] CISA — OpenSSF Scorecard — https://www.cisa.gov/resources-tools/services/openssf-scorecard
[12] OpenSSF — Scorecard: Security health metrics for Open Source — https://scorecard.dev
[13] CyberDesserts — npm Security Risks 2026: Vulnerable Packages & Fixes — https://blog.cyberdesserts.com/npm-security-vulnerabilities/
[14] Trail of Bits Blog — Securing the software supply chain with the SLSA framework (2024) — https://blog.trailofbits.com/2024/10/01/securing-the-software-supply-chain-with-the-slsa-framework/
[15] Zenn — The 2026 State of Package Registry Provenance: Who Is Signing What? — https://zenn.dev/sqer/articles/e4df3d397f5651?locale=en
[16] SLSA — Supply-chain Levels for Software Artifacts — https://slsa.dev
[17] Google Open Source Insights — Introducing PyPI digital attestation support (2024) — https://blog.deps.dev/pypi-attestations/
[18] SecurityArsenal — Google OSS Rebuild: Automating SLSA Provenance and Supply Chain Integrity for PyPI, npm, and Crates — https://securityarsenal.com/blog/google-oss-rebuild-automating-slsa-provenance-and-supply-chain-integrity-for-pypi-npm-and-crates