Trivy filesystem mode: где ломается проверка зависимостей
Проверка зависимостей при сборке ломается чаще не на самой уязвимости, а на способе её поиска. Сканирование состава зависимостей вешают после сборки образа, отдельной задачей и без блокировки — конвейер сборки уязвимости формально зелёный, а в релиз уходит пакет с известной проблемой. Обратный вариант тоже плохой: полное сканирование образа на каждый коммит добавляет минуты к каждой сборке, и шаг отключают, чтобы не ждать.
Trivy filesystem mode снимает обе крайности: он читает манифесты и lock-файлы прямо из рабочей копии — package-lock.json, go.mod вместе с go.sum, pom.xml, requirements.txt или poetry.lock — без собранного образа, доступа к реестру и прав на демон контейнеризации. Достаточно одного исполняемого файла и локального кэша базы уязвимостей, который обновляется отдельным шагом и переиспользуется между запусками, в том числе в закрытом контуре.
Ломается это на многомодульных репозиториях. В монорепо десятки модулей со своими lock-файлами, часть пакетов приходит транзитивно через родительский манифест, часть — инструментальная и тестовая. Без явного списка целей и правил исключения сканирование либо шумит на неподдерживаемых зависимостях, либо молча пропускает модуль, до которого не дошло по дереву. Итог предсказуем: команда привыкает игнорировать красный статус.
Разбираем, как это закрывается — как задать цели сканирования, пороги по критичности и поведение на выход, чтобы шаг оставался быстрым и действительно останавливал сборку.
Что меняется после встраивания проверки в сборку
Встраивание проверки зависимостей в сборку даёт измеримые сдвиги, а не ощущение спокойствия. Ниже — чек-лист, по которому мы сверяем результат на приёмке: каждый пункт считается по логам конвейера и отчётам сканера, а не на словах.
- Время сборки — Trivy в режиме filesystem разбирает манифесты и дерево зависимостей без запуска контейнеров, поэтому прибавка к общему времени идёт на десятки секунд, а не на минуты.
- Доля пойманных уязвимостей — проверка выполняется на каждом коммите, находка фиксируется до выката; в отчёте видно срез по уровням критичности и динамику от релиза к релизу.
- Ушедший класс отказов — из выкатов исчезают падения из-за несовместимых или отозванных версий библиотек: их отсекает сборка, а не дежурный ночью.
- Стоимость простоя — измеряется часами недоступности и числом ручных откатов; когда проблема ловится до выката, восстановление не требуется вовсе.
- Читаемость отчёта — вывод ограничиваем новыми находками относительно базовой линии, поэтому в отчёт попадает только то, что появилось в текущем изменении.
- Воспроизводимость — ту же проверку инженер запускает локально перед коммитом, и результат совпадает с тем, что видит конвейер.
Отдельно настраиваем пороги: блокировать сборку на критичных уровнях и предупреждать на остальных. Без этого шум в отчёте быстро приводит к тому, что проверку начинают обходить, и она перестаёт ловить что-либо.
Режимы сканирования: файловая система, образ, реестр
Точка проверки определяет, что сканер вообще способен увидеть. Trivy в режиме filesystem читает манифесты и lock-файлы прямо в рабочем каталоге: это самый быстрый вариант, секунды на прогон, годится для pre-commit и ранних шагов сборки. Проверка готового образа даёт полную картину — слои, системные библиотеки, пакеты, доустановленные поверх базовой основы. Удалённый реестр образов проверяет то, что уже опубликовано и работает в среде.
| Точка проверки | Когда подходит | Ограничения |
|---|---|---|
| Файловая система | Разработка, pre-commit, проверка манифестов до сборки | Не видит пакеты из базового слоя и системные библиотеки |
| Готовый образ | Ворота перед публикацией, проверка того, что реально запустится | Нужны собранный артефакт и локальный демон, прогон дольше |
| Удалённый реестр | Аудит опубликованных тегов, регулярный пересмотр без пересборки | Нет доступа к локальным слоям, есть зависимость от доступности реестра |
Режимы сканирования не заменяют, а дополняют друг друга: файловая система ловит проблему на входе, готовый образ — до публикации, реестр — после. Расхождение между результатами нормально, потому что часть зависимостей приходит из базового слоя и в файлах проекта не видна.
Общее ограничение — актуальность базы уязвимостей. Без регулярного обновления индекса любой режим даёт недостоверную картину, а кэш базы стоит фиксировать по версии, иначе прогоны между сборками несопоставимы.
Выбор точки — это выбор места ворот: где отказ обходится дешевле, там и ставим проверку.
Этапы внедрения проверки состава зависимостей
Порядок работ строим так, чтобы проверка состава зависимостей встраивалась поверх существующего конвейера, а не вместо него. Сначала фиксируем текущее состояние, затем включаем сканирование в режиме отчёта и только после обкатки делаем проверку блокирующей — так сборка не встанет в первый же день, а команда успевает разобрать накопленные замечания.
- Аудит конвейера. Смотрим, как собираются артефакты, где лежат манифесты и файлы зависимостей, какие стадии уже есть и на какую из них проверка встанет без перестройки сборки.
- Схема проверок. Определяем охват — деревья репозиториев и собранные образы — и точку запуска Trivy filesystem mode: до сборки, чтобы не тратить время на заведомо проблемный коммит.
- Настройка порогов блокировки. Разделяем находки по уровням: что останавливает сборку, что уходит в отчёт, что внесено в список принятых рисков с причиной и ответственным.
- Обкатка в режиме отчёта. Первые прогоны не блокируют, а собирают статистику: сколько срабатываний, какие повторяются, где ложные. По ней калибруем пороги.
- Перевод в блокирующий режим. Включаем остановку по критичным уровням и формулируем сообщение разработчику так, чтобы было понятно, что именно обновить или заменить.
- Передача настроек команде. Отдаём правила, схему запуска, порядок обновления списка исключений и точку обращения при срабатывании — дальше конвейер работает без нас.
Что остаётся в репозитории после внедрения
После внедрения в репозитории остаётся не набор разовых команд, а комплект артефактов. Trivy в режиме сканирования файловой системы запускается из файла конфигурации, поэтому результат воспроизводится одинаково и на локальной машине, и в конвейере.
- Конфигурация проверки — единый файл в корне: цели сканирования, уровни серьёзности, форматы отчётов, поведение сборки при находке.
- Правила отсечения срабатываний — список исключений, где напротив каждого указано обоснование: почему уязвимость не применима к профилю использования сервиса.
- Политики доступа — кто вправе править исключения и утверждать новые, как ведётся история правок и кто делает ревью.
- Регламент обновления базы — периодичность синхронизации, поведение сборки при недоступном источнике, ответственный за обновление.
- Документация по проверкам — раздел в README: как запустить проверку локально, что означает упавшая сборка, где смотреть отчёт.
- Матрица серьёзности — какие уровни блокируют сборку, какие уходят в отчёт и попадают в план работ.
- Шаблон для новых сервисов — базовый набор файлов, чтобы новый репозиторий стартовал с проверками, а не догонял остальные.
Такой комплект переживает смену инженеров и переезд проекта: проверки поднимаются по документации, а не по памяти коллеги. Отдельно следим, чтобы список исключений не разрастался — пересматриваем его по расписанию и убираем правила, потерявшие основание.
Кейс: доля сборок с уязвимыми зависимостями снизилась
Проект — платформа из нескольких десятков сервисов с общим конвейером сборки. Проверку зависимостей здесь делали после сборки образа: результат приходил через 10–12 минут, уже после публикации артефакта, и воспринимался как справочная информация. Доля сборок в основной ветке с уязвимыми зависимостями высокого уровня держалась около 27%.
Что сделали
Мы перенесли проверку в начало конвейера и перевели её на Trivy в режиме сканирования файловой системы. Прогон идёт по дереву исходников — манифестам и файлам блокировки зависимостей — до сборки образа, поэтому не ждёт готового артефакта и не требует доступа к реестру.
База уязвимостей кэшируется между запусками, пороги и исключения заданы файлом конфигурации, а отчёт отдаётся в разметке, которую система контроля версий показывает как замечания прямо в запросе на слияние. Блокирует только критичная уязвимость с доступным исправлением — остальное уходит в очередь задач.
Результат
После перехода проверка одного сервиса занимает около 40 секунд вместо 12 минут, и разработчик видит итог в первую минуту. Доля сборок с уязвимыми зависимостями снизилась с 27% до 4%, а восемь из десяти исправлений попадают в тот же запрос на слияние, где уязвимость нашлась.
Подтверждали эффект по журналам сборок и сверке отчётов до и после: считали долю уязвимых сборок по неделям, а не по отдельным релизам, чтобы исключить разовый результат.
Чем Trivy отличается от проверки на стороне реестра?
Проверка на стороне реестра работает с уже собранным образом — слоями, базой пакетов, содержимым файловой системы. Точка входа одна и она последняя: годится как финальный барьер перед выкаткой, но сигнал приходит после сборки и публикации тега, когда контекст задачи у разработчика уже потерян.
Trivy в режиме filesystem сканирует рабочий каталог до сборки: lock-файлы и манифесты зависимостей, Dockerfile, манифесты Kubernetes, конфигурации и случайно закоммиченные секреты. Охват проверки смещается с артефакта на источник — видно то, что ещё только попадёт в образ, и проблема закрывается на слиянии ветки, а не после публикации.
Цена ошибки тоже разная. Для реестра найденный дефект — это существующий образ, который нужно пересобрать, перевыпустить и заново выкатить в среду. Для filesystem-режима — правка одной строки и упавшая проверка в том же задании, где идут тесты и линтеры; откат не нужен, потому что плохой артефакт не создавался.
Проверка на стороне реестра при этом не отменяется: она видит реальную сборку, включая базовые слои, и покрывает образы, собранные не нашим конвейером. Плюс она перепроверяет уже лежащие в реестре артефакты, когда в базе появляется новая уязвимость, — исходников у старого тега может уже не быть.
Итог: точки проверки не заменяют одна другую, а делят роли. Режим filesystem даёт ранний отказ и обратную связь за минуты в том же прогоне, что и тесты, реестр остаётся последним барьером перед выдачей.
Частые технические сомнения по проверке зависимостей
Сомнения инженеров по проверке зависимостей сводятся к четырём темам: сколько ложных срабатываний придётся разбирать вручную, работает ли разбор в закрытом контуре, насколько он замедляет сборку и как обновляется база уязвимостей без внешних заимствований.
Ниже — короткие ответы на уровне конфигурации. Речь про режим trivy filesystem mode: он читает манифесты и файлы блокировки прямо из рабочей копии, не требуя собранного образа.
Утонем ли мы в ложных срабатываниях?
Пока не настроены фильтры — да. Мы отсекаем неиспользуемые ветви зависимостей, ограничиваем правило уровнем критичности и ведём файл исключений, где у каждой строки есть автор и срок пересмотра. После этого на релиз остаются единицы находок, и каждая требует реального решения.
Работает ли это в закрытом контуре?
Да. База уязвимостей разворачивается во внутреннем реестре артефактов, обновление идёт по расписанию, а сам разбор не обращается во внешнюю сеть. Там, где внешний доступ разрешён, база подтягивается напрямую; в закрытом контуре зеркало проверяется на целостность до прогона, иначе устаревший слепок тихо пропускает находки.
Насколько разбор замедляет сборку?
Заметно только без кэша. Шаг ставим после установки зависимостей, прогоняем по изменённым файлам блокировки, базу держим локально рядом со сборочным агентом. На типовом релизе добавка измеряется секундами; отчёт уходит отдельным артефактом и не блокирует сборку, пока не выставлены пороги.
Обсудим задачу: что прислать для оценки конвейера
Чтобы вернуться с оценкой и планом работ, нам нужны вводные по вашему конвейеру — без них расчёт сроков превращается в догадки. Ниже список того, что мы обычно уточняем на первом разговоре; часть пунктов часто уже есть под рукой.
- Ссылка на репозиторий и файл описания сборки (GitLab CI, GitHub Actions, Jenkinsfile) — по нему видно, на каком этапе сейчас запускаются проверки и где встанет шаг сканирования.
- Языки и менеджеры зависимостей: go.mod, package-lock.json, requirements.txt, pom.xml, composer.lock — от них зависит, какие анализаторы включит Trivy filesystem mode и сколько времени займёт проход.
- Требования к отчётам: нужен SARIF для встроенной панели, JSON для разбора скриптами или таблица в артефактах сборки.
- Политика по уязвимостям: какие уровни критичности останавливают сборку, а какие только логируются; есть ли исключения и файл .trivyignore.
- Ограничения среды: закрытый контур без внешних обращений, свой реестр образов, прокси, локальный кэш баз уязвимостей.
- Регламент разбора находок: кто отвечает за исправление, за какое время закрываются критичные, как оформляется откат при ложном срабатывании.
- Целевые цифры: сколько сейчас длится сборка и какой запас времени на шаг сканирования мы не должны превышать.
Пришлите эти вводные — обсудим задачу и вернёмся с оценкой и планом работ: этапы, что меняем в конвейере, как проверяем результат. Если каких-то данных нет, подскажем, где их взять.







