Перейти к содержимому
>_ITDITDПлатформа веб-безопасности

Руководства по безопасности

Как по-настоящему закрывать CVE в зависимостях: сканировать, исправлять, изолировать и продолжать следить

Плейбук того, как реально закрывать уязвимости (CVE) в зависимостях: определение готовности из 4 частей — скан, фикс, изоляция, мониторинг — и уроки из практики, чтобы исправления не исчезали при следующем деплое (локально → push → деплой).

Опубликовано 2026-06-11 Обновлено 2026-06-11 7 мин чтения

Для тех, кто запускает несколько веб-приложений (разные фреймворки) малой командой и хочет исправить уязвимости зависимостей (CVE) по-настоящему, раз и навсегда. Без шагов атаки — только практика исправления, закрепления исправлений и наблюдения. Про тип инцидента, который часто это запускает, см. заброшенная публичная RCE и мошеннические счета.

Взгляд этого сайта: малые команды остаются в безопасности за счёт двух дисциплин

В малой команде работает не яркий инструментарий, а две дисциплины: 1) автоматическое обнаружение изменений (оповещать только о новых уязвимостях) и 2) локально→push→деплой (продакшен принимает, никогда не правит). Этот сайт работает так же: аудит зависимостей (pnpm audit) перед каждым деплоем плюс ежедневный cron, с push-to-deploy, доставляющим в продакшен. Относиться к безопасности как к «системе, которая продолжает срабатывать», а не как к «разовому исправлению» — самое дешёвое из того, что держится.

Сначала зафиксируйте «определение готовности» из 4 частей

Защита от преждевременного объявления «готово». Решите заранее: пока не сойдутся все четыре, это незавершённо.

1. Скан

перевести состояние в цифры

2. Фикс

корневое исправление не-dev крит/высоких

3. Изоляция/передача

сделать неисправимое явным

4. Мониторинг

наладить ежедневное обнаружение изменений

Работа с уязвимостями готова = набор из четырёх. Пропустите одно — и дыра остаётся под «я исправил».

1. Скан: переведите состояние в цифры

Сначала увидьте, что и где, машинно. Ручные разовые проверки всегда срываются.

1

Автоматически находите lock-файлы и сканируйте

Найдите composer.lock / package-lock.json / pnpm-lock.yaml и прогоняйте их ежедневно через сканер с открытым кодом (osv-scanner или pnpm audit). Он лишь читает lock-файлы, так что нагрузка крошечная.
2

Знайте, что серьёзность — не одно число

Один и тот же изъян может быть High по CVSS (скажем, 7.5), но Moderate по выверенной оценке вендора. CVSS вычисляется машинно и склонен завышать. Решите, какая основа задаёт ваш порог, и убедитесь, что вся команда знает, какая в ходу (→ что такое CVSS). Скрестите с тем, эксплуатируется ли он реально (KEV), для приоритизации.
3

Исключайте шум С записанной причиной, а не игнорированием

Dev-зависимости только для тестов/сборки часто не попадают в продакшен-бандл и могут не нести реального риска. Используйте группировку сканера, чтобы убрать dev из уведомлений, но записывайте, почему вы исключили. Сохраните способность ответить «а это разве всё ещё не исправлено?» позже.

2. Фикс: исправляйте корень, а не прячьте симптом

Первая помощь (сокрытие симптома) и корневое исправление — разные задачи. Сделайте обе, чтобы закончить.

Только сокрытие симптома (сдерживание)

  • блокировать только «подозрительно выглядящие» запросы на обратном прокси
  • симптом прекратился, значит назвать «разобрались»
  • уязвимая зависимость остаётсяRCE живёт дальше

Корневое исправление (правильно)

  • обновить уязвимую зависимость до исправленной версии
  • после обновления убедиться, что сигнатура исчезла из логов
  • считать первую помощь и корневое исправление двумя разными задачами и делать обе

Проверяйте мажорные обновления сборкой ДО продакшена

В отличие от патча, скачок мажорной версии (фреймворк 14→15, UI-кит 4→6 и т. п.) несёт ломающие изменения. Обновить вслепую и сломать прод-сборку — худший случай. Поместите изменённый исходник в идентичную проду среду выполнения (контейнер с той же версией Node/PHP) и добейтесь полностью зелёной сборки/проверки типов до push. Устраняйте ошибки по одной (codemod sync→async, многострочные строки CSS-классов, упразднённое глобальное пространство типов и т. п.). Если старый контейнер продолжает работать, при сбое откат проходит без простоя.

Завершённость включает устойчивость исправления

Идеальное исправление стоит ноль, если следующий деплой его стирает. Это самая частая ловушка.

1

Не коммитьте в продакшен-дереве

Прямой коммит в продакшене разветвляет историю от центрального репозитория, и следующий деплой (pull / checkout -f) перезаписывает его, и исправление исчезает. Продакшен — это «куда приземляются результаты деплоя», а не где вы правите.
2

Стандартизируйте одно направление: локально→push→деплой

Правьте локально → коммит → push → (продакшен) делает pull / автодеплой. Даже изменение, которое пришлось проверять на продакшене, нужно отмотать на локаль и заново запушить (→ сделать продакшен только на приём).
3

Не доверяйте HTTP 200 как «здоровью»

На шаред-хостинге фатальная ошибка всё равно может вернуть 200. Проверяйте по реальному содержимому — отрисован ли ожидаемый заголовок/текст (curl | grep), нет ли новых ошибок в логах, и пройдите по динамическим маршрутам (на БД, с параметрами), а не только по главной. Кэши могут задержать изменение, так что подождите или сначала очистите.

3. Изоляция/передача: сделайте неисправимое явным

Не всегда можно исправить всё сейчас. Хитрость — никогда не оставлять «не могу исправить / не моя зона / не используется» неопределённым.

1

Осиротевший/EOL код: изолируйте ПЕРЕД удалением

Старый исходник, который вы больше не обслуживаете (EOL-фреймворки и т. п.), — не удаляйте напрямую; переименуйте для изоляции и оставьте пометку, когда/почему и где он обслуживался. Уберите его и из сканов. «Удалить» необратимо; «изолировать» обратимо и сохраняет след.
2

Сначала убедитесь, что на него реально нет ссылок

Проследите конфигурацию обратного прокси, настройку сборки и монтирования, чтобы убедиться, что ничто на него не ссылается, прежде чем изолировать, — отрежьте риск случайного повторного обслуживания.
3

Явно передавайте то, что не можете исправить

То, что вне вашей досягаемости, передавайте с указанием «кто / что», а не оставляйте. Ценность инвентаризации — не дать неисправленному превратиться в невидимую запущенность.

4. Мониторинг: готово только с ежедневным обнаружением изменений

Теперь, наконец, поставьте механизм срабатывания. Без него сделанное исправление не сообщит вам, когда оно повторится.

Оповещайте о НОВОМ, а не обо всём каждый день

Сравнивайте результаты скана с предыдущим прогоном (файлом состояния) и уведомляйте только при появлении нового критического/высокого. Одно и то же содержимое каждый день начинают игнорировать (усталость от оповещений). Сводите в одно письмо (новые / устранённые / текущие) по ежедневному cron. Даже шаред-хостинг нормально тянет один бинарник сканера + cron (нагрузка — миллисекунды; добавьте nice для спокойствия).

diff
уведомлять только о новом = без усталости
ежедневно
держите запущенным на cron
1 письмо
сводка новые / устранённые / текущие
все 4
готово только когда включён мониторинг

«Секреты» и «ключи», которые инвентаризация тоже всплывает

Реальное закрытие CVE склонно всплывать и не-зависимостные дыры. Две классики — файл секрета, оставленный в публичной директории (старый токен в веб-корне; если он из общего шаблона, у каждого сайта та же дыра) и корневой ключ, выданный среде, которую можно скомпрометировать. Оба создают паттерн «одна утечка — всё», так что проверяйте их в том же проходе (каждое заслуживает отдельного разбора). По основам секретов см. безопасное хранение секретов и базовый чек-лист.

Читать дальше

FAQ

QКогда работа с уязвимостями действительно «завершена»?
A

Только когда сходятся четыре вещи: 1) вы просканировали и перевели состояние в цифры, 2) вы исправили не-dev критические/высокие, 3) вы явно изолировали или передали то, что не можете исправить / осиротевший код, и 4) вы наладили ежедневное обнаружение изменений (мониторинг, ловящий новые и повторяющиеся проблемы). Пока нет п. 4, это не готово — зависимости снова станут уязвимыми завтра.

QНе вызовет ли ежедневное сканирование усталость от оповещений?
A

Оповещение обо всём ежедневно быстро начинают игнорировать. Сравнивайте с предыдущим результатом (файлом состояния) и уведомляйте только при появлении НОВОГО критического/высокого — обнаружение изменений. Не отправлять одно и то же каждый день — вот что делает мониторинг по-настоящему долговечным.

QПочему исправление иногда откатывается к уязвимому?
A

Коммит прямо в продакшен-дереве означает, что следующий деплой (pull или checkout -f) перезаписывает и стирает исправление. Стандартизируйте одно направление — локально→push→деплой — и сделайте продакшен «только на приём». Идеальное исправление в процессе, который его стирает, стоит ноль.