
jackson-databind 2026년 11건의 보안 공지 자가 점검: 소스 코드 주석을 스캔해 노이즈를 줄이고, 실제로 해당되는 건이 몇 건인지 알려줍니다. 항목별 교집합을 구해 진정으로 충분한 버전(2.18.9/2.21.5/3.1.5, advisory에서 가장 흔히 언급되는 2.21.4가 아님)을 제시합니다. CVE-2026-54515 / CVE-2026-54512
jackson-databind 2026년 11건 보안 권고 자가 점검 도구. 제로 의존성 단일 jar, 오프라인.
Dependabot이 답하지 못하는 두 가지 질문에 답합니다:
@JsonView / 다형성 타입 / 대소문자 비구분 매칭……)을 찾아내, "영향받는 버전 설치됨"을 "그 기능을 실제로 사용함"으로 노이즈를 줄입니다.java -jar jackson-check.jar ./target ./src
2026년 이 11건 중 8건이 수정 버전을 2.21.4 / 2.18.8 / 3.1.4로 명시합니다. 그대로 올린 사람은 수리가 끝났다고 생각합니다.
실제로 건별 교집합을 구한 답:
목표를 높이는 건 이 세 건입니다:
CVE-2026-54515 — 대소문자 비구분 역직렬화가 속성별 @JsonIgnoreProperties를 우회
CVE-2026-59889 — @JsonView가 @JsonUnwrapped 컨테이너 속성에 적용되지 않음
🔴 GHSA-mhm7-754m-9p8w — CVE 번호 없음, advisory 원문에 다음과 같이 적혀 있음:
the fix was never backported to 2.21 or 2.18 … Users on 2.21.4 and 2.18.8 who upgraded per the published advisories remain vulnerable
이것은 패치 갭입니다: 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뿐임 |
그런데 advisory의 구조화된 필드에는:
com.fasterxml.jackson.core에 3.x 범위 6건이 걸려 있고, 수정 버전 3.1.4 → 해당 좌표에서 HTTP 404tools.jackson.core에 2.x 범위 1건이 걸려 있고, 수정 버전 2.21.4 → 역시 HTTP 404advisory를 그대로 복사한 도구는 존재하지 않는 것을 설치하라고 안내할 것입니다. 이 도구는 판정표 생성 시 각각 HEAD 요청으로 실제 획득 가능 여부를 검증하며, 받을 수 없는 것은 보고서에 표시하고 업그레이드 권장으로 출력하지 않습니다.
두 좌표의 artifactId와 jar 파일 이름은 완전히 동일하며, META-INF에서만 구분할 수 있습니다 — 그래서 이 도구는 파일 이름이 아닌 좌표로 판정합니다.
같은 2.18.5, 두 코드의 결과는 완전히 다릅니다:
다형성 타입 + @JsonView를 사용한 코드 → Dependabot 7건 보고, 실제 6건 해당
ObjectMapper만 new 한 코드 → Dependabot 7건 보고, 실제 0건 해당
양방향 모두 명확히 해야 합니다. 한쪽만 말하면 오해를 만듭니다:
① "트리거 조건을 찾지 못함"이 안전을 의미하지 않음. 세 가지 경우가 거짓 안심을 만들 수 있습니다:
ObjectMapper.addMixIn) 같은 런타임 방식으로 추가될 수 있어, 소스 코드에 그 단어 자체가 없음;② "트리거 조건이 모두 성립"이 확정적으로 감염됐다는 뜻도 아님. 마커는 코드베이스 전체 기준으로 집계되며, 같은 클래스나 같은 필드 기준이 아닙니다. 예를 들어 어떤 항목은 @JsonView와 @JsonUnwrapped가 같은 속성에 적용되어야 하는데, 우리는 두 단어가 모두 코드에 등장했다는 것만 볼 수 있습니다.
이 도구는 텍스트 매칭만 수행하며 AST 파싱을 하지 않습니다. 이는 의도적인 절충입니다: 핵심 경로는 사람이 읽고 직접 검증할 수 있어야 합니다 — 이해할 수 없는 AST 판정이 틀렸을 때 아무도 발견할 수 없기 때문입니다.
버전 판정(1단계)은 확정적입니다. 트리거 조건 판정(2단계)은 우선순위를 정하는 데만 쓰이며, 위험을 면제하는 데 쓰이지 않습니다.
Dependabot 사각지대에 관해: 이번 11건은 하나도 해당하지 않습니다. 공식 저장소 advisory 페이지 11건, 두 좌표로 역조회한 합계 11건, 차이 0 — 이것은 두 소스를 조회한 후 내린 결론이며, 한 소스만 조회한 기본값이 아닙니다(tools/gen_rules.py의 ASSERT2는 다시 실행할 때마다 재검증합니다). 따라서 이번 건들에 대한 Dependabot의 버전 경고는 정확하며, 이 도구의 가치는 노이즈 감소와 교집합 계산에 있고, 누락 보완에 있지 않습니다.
java -jar jackson-check.jar <경로...> [옵션]
<경로> jar / war / 디렉터리. 디렉터리는 빌드 산출물(버전 판정)과 .java 소스(트리거 조건 판정)를 모두 찾음
--src <경로> 소스 디렉터리 추가 지정
--no-src 소스 스캔 안 함(버전만으로 판정, Dependabot과 동일한 세분화)
--all 해당되지 않은 항목도 나열
-v, --version 버전 번호
-h, --help 도움말
종료 코드: 0 = 버전 해당 없음 · 2 = 버전은 해당하지만 소스에서 트리거 조건을 찾지 못함(또는 소스 미스캔)· 3 = 트리거 조건도 성립. CI에서 직접 사용 가능.
인식 가능한 형태: 일반 jar, Spring Boot fat jar(BOOT-INF/lib/), 기존 WAR(WEB-INF/lib/), 호스트 jar에 shade된 jackson(의존성 좌표는 보이지 않지만 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는 두 개의 1차 소스에서 CveTable.java를 생성합니다:
/repos/FasterXML/jackson-databind/security-advisories — 유지보수자가 공개한 항목 전체 + 설명 원문/advisories?ecosystem=maven&affects=<좌표> — Dependabot이 실제로 사용하는 좌표 인덱스(두 groupId 각각 조회)11건의 advisory는 37개의 "advisory × 좌표 × 버전 범위" 규칙으로 확장되며, **13개의 단언(assertion)**이 있어 하나라도 불충족하면 중단하고 파일을 쓰지 않습니다 — "파싱 실패로 빈 껍데기 테이블이 생성돼도 테스트는 그대로 통과"하는 상황을 방지합니다:
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
| 유지 브랜치 | advisory에서 가장 흔한 버전 | 실제로 충족되는 버전 |
|---|
| 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 | PolymorphicTypeValidator 제네릭 파라미터 우회 |
| CVE-2026-54513 | high 8.1 | allowIfSubTypeIsArray() 배열 서브타입 allowlist 우회 |
| 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 setter가 여전히 private 필드를 통해 작성될 수 있음 |
| CVE-2026-54517 | medium 5.3 | @JsonView가 setterless creator 속성에 적용되지 않음 |
| CVE-2026-54518 | medium 6.5 | @JsonView가 unwrapped creator 파라미터에 적용되지 않음 |
| CVE-2026-59888 | medium 6.5 | Record 속성의 @JsonIgnore가 명명 전략에 의해 우회됨 |
| CVE-2026-59889 | medium 6.5 | @JsonView가 @JsonUnwrapped 컨테이너 속성에 적용되지 않음 |
| GHSA-mhm7-754m-9p8w | medium 6.5 | CVE 번호 없음 · @JsonView + As.EXTERNAL_PROPERTY 패치 갭 |