
jackson-databind: самопроверка по 11 бюллетеням безопасности за 2026 год — сканирует аннотации в исходном коде для снижения шума и показывает, сколько из них вас реально касаются; по пунктам вычисляет пересечение и выдаёт действительно корректную версию (2.18.9/2.21.5/3.1.5, а не самую распространённую в бюллетенях 2.21.4). CVE-2026-54515 / CVE-2026-54512
Инструмент самопроверки по 11 бюллетеням безопасности jackson-databind за 2026 год. Один jar без зависимостей, без обращения к сети.
Он отвечает на два вопроса, на которые Dependabot ответить не может:
@JsonView / полиморфные типы / регистронезависимое сопоставление…), снижая шум с «установлена затронутая версия» до «действительно задействована та самая функциональность».java -jar jackson-check.jar ./target ./src
Из этих 11 записей за 2026 год в 8 указано, что исправленная версия — 2.21.4 / 2.18.8 / 3.1.4. Те, кто обновился по этим рекомендациям, считают, что всё исправлено.
Реальный ответ при пересечении по каждой записи таков:
Планку поднимают именно эти три:
CVE-2026-54515 — регистронезависимая десериализация в обход @JsonIgnoreProperties для отдельных свойств
CVE-2026-59889 — @JsonView не действует для контейнерного свойства @JsonUnwrapped
🔴 GHSA-mhm7-754m-9p8w — номера CVE нет, в оригинальном тексте бюллетеня сказано:
исправление так и не было перенесено в 2.21 или 2.18 … Пользователи 2.21.4 и 2.18.8, обновившиеся в соответствии с опубликованными бюллетенями, остаются уязвимыми
Это пробел в исправлениях: в ветке 3.x исправили, а обратный перенос в ветки 2.18 / 2.21 упустили. Из-за отсутствия номера CVE найти её по номеру CVE невозможно.
Достаточно одного запуска, чтобы увидеть:
# 已经升到 2.21.4 的项目
java -jar jackson-check.jar ./lib ./src
# Dependabot 会报给你:3 条
# 🔥 注意:如果你照着 advisory 里出现最多的那个修复版升,以下 3 条仍然中
| Координата | Что реально публиковалось в Maven Central |
|---|---|
com.fasterxml.jackson.core:jackson-databind | Только 2.x |
tools.jackson.core:jackson-databind | Только 3.x |
А в структурированных полях бюллетеней:
com.fasterxml.jackson.core висит 6 диапазонов 3.x, исправленная версия 3.1.4 → по этой координате HTTP 404tools.jackson.core висит 1 диапазон 2.x, исправленная версия 2.21.4 → тоже HTTP 404Инструмент, который слепо копирует advisory, заставит вас устанавливать несуществующий артефакт. Этот инструмент при генерации таблицы решений фактически проверяет доступность отдельными HEAD-запросами; всё недоступное помечается в отчёте и не выводится как рекомендация по обновлению.
artifactId и имена jar-файлов у обеих координат идентичны, различить их можно только внутри META-INF — поэтому этот инструмент судит по координате, а не по имени файла.
Один и тот же 2.18.5 — а результаты для двух проектов совершенно разные:
一份用了多态类型 + @JsonView 的代码 → Dependabot 报 7 条,真中 6 条
一份只 new 了个 ObjectMapper 的代码 → Dependabot 报 7 条,真中 0 条
Нужно чётко сказать про обе стороны: говорить только об одной — значит вводить в заблуждение.
① «Условия срабатывания не найдены» не равно «безопасно». Три ситуации превращают это в ложное спокойствие:
ObjectMapper.addMixIn), и в исходниках этого слова вообще нет;② «Все условия срабатывания выполнены» тоже не означает, что уязвимость подтверждена. Маркеры агрегируются по всей кодовой базе целиком, а не по одному классу или одному полю. Например, для какой-то записи требуется, чтобы @JsonView и @JsonUnwrapped стояли на одном и том же свойстве, а мы видим лишь, что оба слова встречаются в вашем коде.
Этот инструмент выполняет только текстовое сопоставление, а не AST-разбор. Это осознанный компромисс: ключевой путь должен быть читаемым и проверяемым человеком — ошибку в решении, основанном на непонятном AST, никто не заметит.
Определение версии (шаг 1) — жёсткое; определение условий срабатывания (шаг 2) служит только для расстановки приоритетов, а не для снятия риска.
Что касается «слепой зоны» Dependabot: в этой партии из 11 записей её нет ни одной. На странице бюллетеней официального репозитория — 11 записей, обратная проверка по двум координатам даёт в сумме 11, разница равна 0. Это вывод, сделанный после проверки двух источников, а не значение по умолчанию из одного источника (ASSERT2 в tools/gen_rules.py при каждом перезапуске проверяет это заново). Поэтому в этой партии предупреждения Dependabot о версиях точны; ценность данного инструмента — в снижении шума и вычислении пересечений, а не в закрытии пропусков.
java -jar jackson-check.jar <路径...> [选项]
<路径> jar / war / 目录。目录会同时找构建产物(定版本)和 .java 源码(定触发条件)
--src <路径> 额外指定源码目录
--no-src 不扫源码(只按版本判,粒度等同 Dependabot)
--all 把未命中的条目也列出来
-v, --version 版本号
-h, --help 帮助
Коды выхода: 0 = версия не затронута · 2 = версия затронута, но в исходниках условия срабатывания не найдены (или исходники не сканировались) · 3 = условия срабатывания также выполнены. Можно использовать в CI.
Распознаваемые форматы: обычный jar, fat jar Spring Boot (BOOT-INF/lib/), классический WAR (WEB-INF/lib/), jackson, зашэденный в jar-хост (координаты зависимостей не видны, но META-INF/maven на месте).
# Maven 项目
mvn package && java -jar jackson-check.jar target src
# 只有一个成品 jar
java -jar jackson-check.jar app.jar
# Gradle 项目
java -jar jackson-check.jar build/libs src/main/java
Требуется Java 17+. В рантайме ноль зависимостей — в частности, сам jackson не нужен.
tools/gen_rules.py генерирует CveTable.java из двух первоисточников:
/repos/FasterXML/jackson-databind/security-advisories — полный набор записей, опубликованных мейнтейнерами, + оригинальный текст описаний/advisories?ecosystem=maven&affects=<坐标> — индекс координат, который фактически использует Dependabot (по одному запросу на каждый groupId)11 бюллетеней разворачиваются в 37 правил «advisory × координата × диапазон версий» с 13 утверждениями: если любое из них не выполняется, работа прекращается и файл не записывается — защита от ситуации «при ошибке парсинга создаётся пустая таблица, а тесты всё равно зелёные»:
python tools/gen_rules.py # 需要已登录的 gh CLI
56 модульных тестов + 7 сквозных сценариев на реальных артефактах (настоящие jar: 2.13.0 / 2.18.5 / 2.21.2 / 2.21.4 / 2.21.5 / 3.1.2 / 3.1.5).
Apache-2.0
| Ветка поддержки | Самая частая в бюллетенях | Реально достаточная версия |
|---|
| 2.18.x | 2.18.8 | 2.18.9 |
| 2.21.x | 2.21.4 | 2.21.5 |
| 2.22.x | — | 2.22.1 |
| 3.1.x | 3.1.4 | 3.1.5 |
| 3.2.x | — | 3.2.1 |
| Условие срабатывания | Связанные записи |
|---|
@JsonView | CVE-2026-54517 / 54518 / 59889 / GHSA-mhm7 |
@JsonTypeInfo / activateDefaultTyping / PolymorphicTypeValidator | CVE-2026-54512 / 54513 |
@JsonIgnoreProperties + ACCEPT_CASE_INSENSITIVE_PROPERTIES | CVE-2026-54515 |
@JsonIgnore + переименование через @JsonProperty | CVE-2026-54516 |
Java Record + PropertyNamingStrategy + @JsonIgnore | CVE-2026-59888 |
Поле InetSocketAddress | CVE-2026-54514 |
readTree() + JsonNode.toString() | CVE-2026-50193 |
| Утверждение | Что проверяется |
|---|
| ASSERT2 | ⭐ Сравнение «слепых зон» двух источников: разница должна быть равна 0 или объяснена по каждой записи |
| ASSERT6 | Должны быть покрыты оба groupId |
| ASSERT7 | Для каждой исправленной версии выполняется HEAD-запрос для проверки доступности в Maven Central |
| ASSERT8 | Двусторонний «призрак»: получение maven-metadata.xml доказывает, что целой мажорной ветки по этой координате не существует |
| ASSERT9 | Пересечение по каждой ветке, и оно должно быть строго выше минимальной исправленной версии в той же ветке |
| ASSERT11 | Якорная строка каждого условия срабатывания должна посимвольно встречаться в оригинальном тексте официального описания |
| ASSERT12 | У каждой записи должен быть балл CVSS (объединение двух источников) |
| Номер | Уровень | Тема |
|---|
| CVE-2026-54512 | high 8.1 | Обход generic-параметра PolymorphicTypeValidator |
| CVE-2026-54513 | high 8.1 | Обход allowlist для подтипов-массивов через allowIfSubTypeIsArray() |
| CVE-2026-50193 | medium 7.5 | Переполнение стека при глубокой вложенности JsonNode.toString() |
| CVE-2026-54514 | medium 5.3 | Десериализация InetSocketAddress инициирует DNS-запрос (SSRF) |
| CVE-2026-54515 | medium 5.3 | Регистронезависимое восстановление перекрывает @JsonIgnoreProperties |
| CVE-2026-54516 | medium 5.3 | Переименованный сеттер @JsonIgnore по-прежнему допускает запись через приватное поле |
| CVE-2026-54517 | medium 5.3 | @JsonView не действует для свойства creator без сеттера |
| CVE-2026-54518 | medium 6.5 | @JsonView не действует для unwrapped-параметра creator |
| CVE-2026-59888 | medium 6.5 | @JsonIgnore на Record-свойстве обходится стратегией именования |
| CVE-2026-59889 | medium 6.5 | @JsonView не действует для контейнерного свойства @JsonUnwrapped |
| GHSA-mhm7-754m-9p8w | medium 6.5 | Без номера CVE · пробел в исправлении @JsonView + As.EXTERNAL_PROPERTY |