Содержание

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

Разберём, чем опасны старые зависимости, как устроены версии, как автоматизировать обновления и как защититься от вредоносных пакетов.

Почему устаревшие зависимости опасны?

Современный проект состоит из сотен сторонних пакетов. В каждом регулярно находят уязвимости, а исправления выходят только для актуальных версий. Чем дальше проект отстаёт, тем дороже каждый следующий шаг.

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

О других источниках долга — статья технический долг.

Как читать номера версий?

Большинство пакетов следуют семантическому версионированию: номер вида МАЖОР.МИНОР.ПАТЧ. По нему можно понять, насколько рискованно обновление.

Часть версии Что меняется Риск обновления Пример
Патч Исправления ошибок Низкий 3.4.1 → 3.4.2
Минор Новые возможности, совместимые со старым кодом Невысокий 3.4.2 → 3.5.0
Мажор Несовместимые изменения Высокий, нужна миграция 3.5.0 → 4.0.0

Диапазоны версий в файле зависимостей задают, что можно обновлять автоматически, а lock-файл фиксирует точные установленные версии. Lock-файл коммитят в репозиторий, чтобы у всех стояло одно и то же.

Множество металлических шестерней Фото: Unsplash

Как автоматизировать обновления?

Обновления автоматизируют ботами, которые регулярно проверяют новые версии и открывают пулл-реквесты. CI прогоняет тесты, и если всё зелёное, патч-обновления можно вливать почти без участия человека.

{
  "extends": ["config:recommended"],
  "schedule": ["before 9am on monday"],
  "packageRules": [
    { "matchUpdateTypes": ["patch", "minor"], "groupName": "minor and patch", "automerge": true },
    { "matchUpdateTypes": ["major"], "labels": ["major-update"], "automerge": false }
  ],
  "vulnerabilityAlerts": { "labels": ["security"], "schedule": ["at any time"] }
}

Правила процесса:

  1. Патч и минорные обновления группируются и приходят раз в неделю.
  2. Исправления безопасности приходят сразу и имеют высший приоритет.
  3. Мажорные обновления разбираются вручную и планируются как задачи.
  4. Без хороших автотестов автоматическое слияние включать нельзя — подробнее в статье какие автотесты нужны продукту.

Как обновлять мажорные версии фреймворка?

Мажорное обновление фреймворка — это небольшой проект: нужно прочитать руководство по миграции, обновить код, связанные пакеты и проверить всё приложение. Чем раньше после выхода новой версии его сделать, тем меньше изменений придётся вносить.

  • обновляйтесь по одной мажорной версии, не перепрыгивая;
  • сначала уберите всё, что помечено устаревшим в текущей версии;
  • используйте инструменты автоматической миграции кода, если они есть;
  • проверьте совместимость ключевых пакетов заранее;
  • выпускайте обновление отдельным релизом, а не вместе с новыми функциями.

Про новые версии PHP — статья PHP 8.6: релиз-кандидат.

Как защититься от вредоносных пакетов?

Атаки на цепочку поставок — когда злоумышленник публикует вредоносную версию популярного пакета или пакет с похожим названием — стали обычным делом. Защита строится на контроле того, что и откуда устанавливается.

  • проверяйте новые зависимости перед добавлением: популярность, поддержка, количество собственных зависимостей;
  • используйте lock-файл и устанавливайте строго по нему в CI;
  • не обновляйте пакеты в первые дни после выхода версии без необходимости;
  • сканируйте зависимости на известные уязвимости в CI;
  • ограничьте выполнение скриптов установки пакетов, где это возможно.

О других мерах безопасности — статьи OWASP Top 10 простыми словами и секреты в проекте.

Коротко

  • Обновляйте зависимости регулярно и небольшими порциями.
  • Семантические версии показывают риск: патч, минор, мажор.
  • Автоматизируйте пулл-реквесты с обновлениями и проверяйте их тестами.
  • Мажорные версии фреймворка обновляйте по одной, планово и отдельным релизом.
  • Защищайтесь от вредоносных пакетов: lock-файл, проверка новых зависимостей, сканирование.

Частые вопросы

  • Как часто обновлять зависимости?

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

  • Что делать, если библиотеку перестали поддерживать?

    Найти поддерживаемую замену или форк, оценить объём миграции и запланировать её. Если замены нет, а код небольшой, иногда проще перенести нужную часть в свой проект.

  • Нужно ли коммитить lock-файл?

    Да, для приложений обязательно. Lock-файл фиксирует точные версии всех зависимостей, чтобы у всех разработчиков, в CI и на продакшене стояло одно и то же.