Уязвимые зависимости: как найти и исправить их в проекте
Практика3 минРедакция Innovialabs
Коротко
Регулярно сканируйте зависимости (npm audit, pip-audit), автоматизируйте обновления через Dependabot или Renovate, коммитьте lock-файлы и чините в первую очередь то, что реально достижимо и эксплуатируемо в вашем приложении.
Коротко
Большая часть кода в типичном проекте — чужие библиотеки, и уязвимости в них находят постоянно. Рабочая схема:
- Сканер находит известные уязвимости:
npm audit,pip-auditи аналоги. - Бот обновлений (Dependabot или Renovate) сам открывает pull request’ы с новыми версиями.
- Lock-файл фиксирует точные версии, чтобы production собирался из того же, что проверили.
- Оценка риска помогает чинить сначала то, что действительно опасно, а не всё подряд.
Сканирование: npm audit и pip-audit
npm audit сверяет дерево зависимостей с базой известных уязвимостей:
npm audit # все зависимости
npm audit --omit=dev # только то, что попадает в production
npm audit fix # обновить в рамках допустимых диапазонов
Осторожно с npm audit fix --force: он может поставить новую мажорную версию с несовместимыми изменениями. Используйте его только осознанно, с прогоном тестов.
Если уязвима транзитивная зависимость, а прямая ещё не обновилась, можно принудительно задать версию через overrides в package.json:
{
"overrides": {
"vulnerable-lib": "^2.3.1"
}
}
Для Python есть pip-audit:
pip install pip-audit
pip-audit -r requirements.txt
Добавьте сканирование в CI, чтобы новые уязвимости появлялись в отчёте сами, а не когда кто-то вспомнит.
Автоматические обновления: Dependabot и Renovate
Dependabot встроен в GitHub. Минимальная настройка:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
groups:
minor-and-patch:
update-types: ["minor", "patch"]
Группировка объединяет мелкие обновления в один pull request, чтобы бот не заваливал команду.
Renovate работает с GitHub, GitLab и другими платформами и гибче в настройке: расписания, автомерж по правилам, группировка по любым признакам.
{
"extends": ["config:recommended"],
"packageRules": [
{
"matchUpdateTypes": ["patch"],
"automerge": true
}
]
}
Автомерж разумен только при хорошем покрытии тестами и обязательных проверках CI.
Как оценить реальную опасность
Сканер показывает уровень серьёзности (часто по шкале CVSS), но не знает, как вы используете библиотеку. Задайте вопросы:
- Попадает ли пакет в production? Уязвимость в инструменте сборки или тестов обычно менее срочная.
- Вызывается ли уязвимая функция? Если проблема в парсере YAML, а вы им не пользуетесь, риск ниже.
- Контролирует ли атакующий входные данные? Уязвимость в обработке пользовательских загрузок опаснее, чем в разборе собственного конфига.
- Есть ли известная эксплуатация? Проверьте, есть ли уязвимость в каталоге CISA KEV и какой у неё показатель EPSS — вероятность эксплуатации.
Если решили не чинить сейчас — зафиксируйте решение и причину, а не просто игнорируйте предупреждение.
Lock-файлы
- Всегда коммитьте
package-lock.json,pnpm-lock.yaml,poetry.lockили аналог. - В CI ставьте зависимости командой
npm ci: она устанавливает строго по lock-файлу и падает при расхождениях. - В Python закрепляйте версии через pip-tools, Poetry или uv; для дополнительной защиты используйте хеши пакетов.
Без lock-файла один и тот же коммит в разные дни собирается с разными версиями, и уязвимость может «приехать» без единого изменения в коде.
Безопасный режим обновлений
- Патчи безопасности для production-зависимостей — сразу, как только тесты прошли.
- Минорные и патч-версии — пачкой раз в неделю или две.
- Мажорные версии — запланированной задачей: прочитать changelog, обновить код, прогнать тесты, выкатить на staging.
- Перед релизом — staging и smoke-тесты, после — мониторинг ошибок.
- Убирайте неиспользуемые зависимости: нет пакета — нет уязвимости.
Частые ошибки
- Игнорировать отчёт, потому что «там всегда что-то красное».
- Запускать
npm audit fix --forceпрямо перед релизом. - Не коммитить lock-файл.
- Копить обновления годами, а потом переходить через несколько мажорных версий сразу.