Пересекая реку Стикс: Spring Boot 3.5 и проблема зомби-зависимостей

от автора

Недавно я разбирал истории CVE, связанные с завершением поддержки Tomcat 8.5, и решил посмотреть на Spring Boot 3.5. Я задался тем же вопросом применительно к Spring Boot: что происходит с уровнем защищённости приложения, когда используемая версия достигает End Of Life (EOL)?

Слепая зона CVE

Обычно жизненный цикл уязвимости представляют так:

  1. Исследователь обнаруживает проблему.

  2. О проблеме сообщают разработчикам проекта.

  3. Уязвимости присваивают идентификатор CVE и оценку критичности.

  4. Разработчики выпускают исправление.

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

Пока проект активно поддерживается, эта схема в целом работает. После окончания поддержки ситуация меняется.

Разработчики обычно видят только результат процесса: предупреждение об уязвимости (advisory), патч или срабатывание сканера. Гораздо реже они задумываются о людях и организациях, которые обеспечивают этот процесс. Кто ищет уязвимости? Кто проверяет отчёты? Кто назначает идентификаторы CVE? Кто готовит исправления?

После EOL этот конвейер не выключается мгновенно, а постепенно останавливается. Исследователи переключаются на поддерживаемые версии, сопровождающие перестают разбирать проблемы старой ветки, а до CNA доходит меньше отчётов. CNA (CVE Numbering Authority) — организация, имеющая право назначать идентификаторы CVE.

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

Река Стикс

Представьте переход проекта от активной разработки и сопровождения к EOL как пересечение реки Стикс, которая в древнегреческой мифологии отделяет мир живых от мира мёртвых.

На «живой» стороне находятся:

  • сопровождающие, которые продолжают анализировать код;

  • исследователи безопасности, отправляющие отчёты;

  • CNA, присваивающие номера CVE;

  • процесс координированного раскрытия уязвимостей;

  • новые исправления и поддерживаемые релизы.

После перехода в EOL становится тихо. Сам код не становится безопаснее только потому, что его больше не сопровождают. Уязвимости не исчезают, а регулярная работа по их поиску, регистрации и устранению прекращается.

Разработчики поддерживаемой ветки могут обнаружить тот же уязвимый фрагмент кода, который присутствует и в старой версии. Однако для EOL-ветки часто нет отдельного отчёта или патча: команда не обязана продолжать её поддержку и не собирается выпускать исправление. Поэтому сведения о проблеме могут не попасть в доступную для сканеров форму.

Я никого не обвиняю и не хочу сказать, что прежняя модель была неправильной. Я благодарен людям, которые создают проекты и делятся ими. Open source остаётся основой современной разработки, и без него наша работа была бы несравнимо сложнее. Проблема заключается не в людях, а в том, что прежняя модель сопровождения всё хуже соответствует рискам цепочки поставок ПО.

Правила изменились, привычки — нет

Раньше EOL-версию часто воспринимали как «старую, но стабильную». Если код давно не меняется и новых CVE нет, он кажется безопасным. Такая логика ненадёжна.

Злоумышленники следят за уязвимостями, найденными в поддерживаемых ветках, и проверяют те же способы атаки на EOL-версиях. Если общий уязвимый код сохранился, старая ветка также может быть скомпрометирована. При этом отдельной записи в CVE для неё может не быть.

Получается опасный разрыв:

  • сопровождающие знают класс проблемы, но не поддерживают старую ветку;

  • база CVE не содержит явной записи для EOL-версии;

  • сканер не видит известного соответствия «версия — уязвимость»;

  • команда получает зелёный результат работы сканера и считает зависимость безопасной;

  • атакующий проверяет старую версию и использует сохранившийся дефект.

Конкретный риск, конечно, нужно подтверждать анализом кода, затронутых версий и условий эксплуатации. Однако сам сценарий вполне реален.

Как это выглядит на практике

Предположим, одна и та же ошибка присутствует в поддерживаемой и EOL-ветках.

Для поддерживаемой ветки процесс выглядит так:

обнаружение дефекта → отчёт → CVE → исправление → обновление зависимости

Для EOL-ветки цепочка может оборваться:

та же ошибка → меньше внимания → нет отдельного отчёта → нет записи для сканера → нет патча

Сканер не обнаруживает проблему не потому, что проверил исходный код и доказал безопасность. Обычно он сопоставляет версии компонентов с известными записями в базах уязвимостей. Если запись отсутствует или не связывает дефект со старой веткой, результат может оказаться ложноотрицательным.

Когда зависимости становятся зомби

После окончания поддержки публичное число новых CVE по ветке обычно становится меньше. Этому есть два объяснения:

  1. Код действительно стабилен и новых уязвимостей в нём мало.

  2. Система обнаружения, регистрации и исправления проблем перестала активно работать.

Для многих проектов второй вариант кажется мне более вероятным. Такие компоненты я называю зомби-зависимостями.

Зомби-зависимость:

  • остаётся в приложении и продолжает исполнять свой код;

  • не получает публичные исправления безопасности;

  • может содержать незарегистрированные или неочевидные уязвимости;

  • отстаёт от поддерживаемых веток;

  • может вызывать предупреждения сканера.

Главный тезис раздела: тишина в базе CVE ≠ стабильность. Иногда она означает, что за компонентом больше никто системно не наблюдает.

Насколько мне известно, никто ещё не проводил исследования этого эффекта. Но спросите любого, кто профессионально поддерживает безопасность open source проекта после EOL. Этот человек наверняка узнает такой сценарий. Это не доказательство того, что каждая EOL-зависимость уже уязвима. Это разумная консервативная модель управления риском.

Spring Boot 3.5: следующий переход

Открытая поддержка Spring Boot 3.5 завершилась 30 июня 2026 года.

Переход затрагивает не только сам Spring Boot. Версия 3.5 управляет набором компонентов Spring, включая Spring Framework 6.2 и соответствующую версию Spring Security. Когда сообщество перестаёт выпускать исправления для этой платформенной линии, значительное количество Java-приложений теряет привычный поток публичных патчей.

Этот сценарий уже происходил

Spring Boot 2.7 завершил открытую поддержку в ноябре 2023 года. Позже для этой линии продолжили появляться уязвимости.

Один из примеров — CVE-2024-38807 — подделка подписи в загрузчике Spring Boot. Эта уязвимость затрагивала версии Spring Boot 2.7.0–2.7.21. Исправленная версия 2.7.22 была доступна только в рамках коммерческой поддержки, тогда как для актуальных на тот момент веток 3.2 и 3.3 исправления вышли как открытые релизы.

Для команд, оставшихся на Spring Boot 2.7, это означало три основных варианта:

  1. Самостоятельно разработать исправление или бэкпортировать его из поддерживаемой ветки.

  2. Использовать коммерческую поддержку.

  3. Принять и формально оформить риск.

Крайне маловероятно, что Spring Boot 3.5 избежит такой участи. После переключения сопровождающих на Spring Boot 4.0 публичный поток исправлений и отчётов для старой ветки будет постепенно уменьшаться. Вопрос не в том, произойдёт ли переход от стабильной зависимости к зомби-зависимости, а в том, насколько быстро начнёт иссякать поток информации.

Время для манёвра ещё есть

Переход в состояние зомби-зависимости происходит постепенно. Это даёт команде время оценить ситуацию до того, как отсутствие предупреждений начнёт создавать ложное чувство безопасности.

Чем раньше организация оценит объём перехода со Spring Boot 3.5 на 4.0, тем больше у неё вариантов:

  • выполнить миграцию по собственному графику;

  • временно использовать коммерческую поддержку как мост;

  • изолировать или заменить отдельные проблемные компоненты;

  • документировать и контролировать временно принятый риск;

  • подготовить тесты, которые помогут выявить несовместимости и скрытые изменения поведения.

Наихудший вариант — ничего не делать, дождаться прекращения сообщений и принять тишину за доказательство безопасности.

Нужна карта, а не только описание местности

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

Итог

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

Переход Spring Boot 3.5 в состояние зомби-зависимости уже приближается. Вопрос только в том, будете ли вы к нему готовы или он застанет вас врасплох. Оцените миграцию на 4.0 заранее, выберите путь обновления или поддержки и не считайте отсутствие новых CVE достаточным основанием признать риск приемлемым.

Комментарий от Лебедева Максима (Developer Advocate Axiom JDK)

Поддержка (OSS) Spring Boot 3.5 завершилась в конце июня. Поэтому описанный переход уже не «приближается» — он начался. Это ещё не доказывает наличие уязвимостей, но рассчитывать на прежний поток публичных исправлений для 3.5.x больше нельзя. (официальное объявление Spring

ссылка на оригинал статьи https://habr.com/ru/articles/1071344/