Зависимость не всегда видна в package.json, composer.json или go.mod. Иногда нужный файл просто скопировали из чужого репозитория, и вместе с ним в проект попали невидимые риски: лицензия, CVE и потерянная история обновлений.
Ручное копирование файлов выглядит безобидно: взяли helper, polyfill, UI-компонент или кусок драйверного кода и положили в репозиторий. Для сканера зависимостей такой файл часто становится «своим». Он не проходит через package manager, у него нет версии, источника и связи с upstream. Значит, команда может не увидеть уязвимость или лицензионное ограничение.
Исследование File-Level Copying Is an Implicit Dependency in Open Source, опубликованное на arXiv 2 июля 2026 года, показывает масштаб проблемы. Авторы изучили World of Code, извлекли 690 500 событий копирования из 0,1% выборки коммитов и отдельно разобрали 3 912 commits с объяснением причины. В работе прямо сказано: копирование убирает четыре сигнала, которые обычно даёт package manager, - происхождение, сопровождение, безопасность и compliance.
С чего начать аудит
Первый проход делайте по файлам, которые выглядят чужими. Это одиночные большие файлы без локальной истории, директории vendor, third_party, external, минифицированные JS/CSS, скопированные UI-assets и код с нестандартным стилем. Посмотрите первый коммит файла: там часто есть ссылка, имя проекта или фраза вроде «copy from upstream».
- Проверьте заголовки файлов: copyright, license, author, URL.
- Найдите похожий код через поиск по уникальной строке или имени функции.
- Сравните найденный upstream с локальной копией через diff.
- Запишите источник, commit/tag и причину копирования в отдельный файл.
Что фиксировать
Минимальная карточка такой зависимости должна содержать путь в проекте, upstream URL, версию или commit, лицензию, способ обновления и ответственного. Если происхождение не восстановлено, так и пишите: «source unknown». Это лучше, чем молчаливо считать файл внутренним.
Цифры из исследования объясняют, почему это не бюрократия. У скопированных источников медианный возраст составил 155 дней, 38,5% были старше года, recoverable origin был задокументирован только в 4,3% случаев, а checkable version - в 2,0%. Даже для vendored-копий источник был записан лишь в 10% случаев.
Как снизить риск
Если файл действительно нужен, лучше оформить его как нормальную зависимость или хотя бы как vendored-копию с документированным upstream. Добавьте запись в SBOM, если проект его выпускает. CycloneDX отдельно описывает use cases для provenance и integrity verification: это как раз данные о происхождении компонента, его изменениях и проверке целостности.
Для безопасности проверьте CVE не только по имени пакета, но и по найденному upstream. В исследовании риск концентрировался в vendored dependencies: 17 314 copy commits были связаны с CVE-risk в полном графе WoC, 88% из них относились к форме dependency-vendoring, а 80% имели CVSS не ниже 7,0. Это не повод удалять все копии, но повод перестать считать их невидимыми.
