Files
llm-wiki/raw/blog-topics/archunit-jackson-default-typing-cve-2019-14379-block-2026-05-29.md
T

102 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: blog-topic / archunit-jackson-default-typing-cve-2019-14379-block-2026-05-29
source_type: blog-topic
status: raw
related_branches: [feature-boundary-validation-mapping-contract]
related_projects: [ca-tmpl]
tags: [blog-topic, ca-tmpl, archunit, jackson, security, cve, fitness-function, polymorphic-deserialization]
created: 2026-05-29
status_label: ready-for-canonical
target_audience: backend-engineer
inspiration_url:
archive_url:
---
# blog-topic: archunit-jackson-default-typing-cve-2019-14379-block-2026-05-29
> Layer: `raw/blog-topics/` — 채용공고가 아닌 작업·학습·트러블슈팅에서 나온 블로그 글감 원석. canonical 정제 전 raw 후보이며, `wiki/blog/` 직접 생성 근거가 아니다.
## Parent / 부모
- [[raw/branch-notes/feature-boundary-validation-mapping-contract]] — B5 결정 + Claims to Verify 의 두 행 `actually-implemented` 승급. 본 글감은 그 enforcement 패스의 보안 측면 단독 추출.
## 트리거 / Trigger
- 트리거 유형: `branch-work`
- 트리거 날짜: 2026-05-29
- 트리거 연결 노트: [[raw/branch-notes/feature-boundary-validation-mapping-contract]] — 1차 enforcement 패스에서 `no_jackson_laissez_faire_subtype_validator` + `no_jackson_enable_default_typing_call` 두 ArchUnit 규칙 + `DefaultTypingFixture` violations-as-data 테스트로 CVE-2019-14379 의 코드 진입점을 정적으로 차단한 작업.
## 글감 / Topic seed
- 한 문장 요지: Jackson polymorphic deserialization 의 RCE 게이트 (`ObjectMapper.enableDefaultTyping()` / `activateDefaultTyping(LaissezFaireSubTypeValidator)`) 는 *런타임 dependency check 가 아니라 컴파일/테스트 단계의 fitness function* 으로 막아야 안전하다 — 한번 머지된 뒤에는 production 트래픽으로 RCE 가 터지는 게 검출 시점이므로 너무 늦다.
- 떠오른 계기: feature-boundary-validation-mapping-contract B5 결정의 enforcement 단계. CVE 자체의 발견 (2019) 과 Jackson 2.10 의 `@Deprecated` 조치 (2019-09) 가 있었음에도, *우리 코드가 호출하지 않는다* 는 사실은 매 PR 마다 사람이 보장해야 하는 규약이었다. 이걸 ArchUnit fitness function 으로 commit 으로 박은 사례.
- 예상 제목 후보:
- CVE-2019-14379 의 호출 경로를 ArchUnit 으로 정적 봉쇄하기
- "Jackson 을 안전하게 쓴다" 를 컨벤션이 아닌 fitness function 으로 박는 방법
- `enableDefaultTyping()` 한 줄이 RCE 가 되는 이유와 정적 차단
## 핵심 주장 후보 / Claim candidates
- 사실 후보:
- CVE-2019-14379 의 RCE 경로는 `ObjectMapper.enableDefaultTyping()` 활성화 + `ehcache` 같은 gadget class 가 classpath 에 있는 조건 — 근거: NVD CVE-2019-14379 (CVSS 9.8), Jackson 보안 가이드 `enableDefaultTyping``@Deprecated since 2.10` 표기.
- Jackson 2.10 의 공식 대체 API 는 `activateDefaultTyping(PolymorphicTypeValidator)` 이며, allowlist 구현체 `BasicPolymorphicTypeValidator` 또는 `@JsonTypeInfo(use = NAME) + @JsonSubTypes` 명시가 정식 — 근거: `raw/official-docs/schema-jackson-polymorphic-deserialization.md#JACK-POLY-C1..C5`.
- `LaissezFaireSubTypeValidator`*모든 subtype 허용* 의 명시적 anti-allowlist — 클래스 이름 그 자체가 "보안 검증 없음" 의 표지 — 근거: `JACK-POLY-C2`.
- ca-tmpl 의 적용: `src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/CleanArchitectureTest.java` 에 두 규칙 추가 — `no_jackson_laissez_faire_subtype_validator` (클래스 참조 차단), `no_jackson_enable_default_typing_call` (메서드 호출 차단). 위반 fixture 는 `violations/boundary/DefaultTypingFixture.java`.
- 규칙 두 개를 분리한 이유: `LaissezFaireSubTypeValidator` *없이* `enableDefaultTyping()` 만 호출해도 (`ObjectMapper.DefaultTyping.NON_FINAL` 등 deprecated overload) 위험. 호출 차단과 import 차단이 *독립적인 진입점* 이므로 둘 다 닫아야 한다.
- 경험 후보:
- ArchUnit DSL 의 `callMethodWhere(target(name(...)))` 패턴은 호출자 의도와 무관하게 *메서드 이름* 으로 catch. `enableDefaultTyping` 이라는 메서드 이름이 ObjectMapper 외부에 존재할 가능성이 거의 0 이므로 owner 필터를 생략해도 false positive 없음 — 단순 규칙이 충분.
- violations-as-data fixture 는 `DefaultTypingFixture.unsafe()` 한 메서드로 두 규칙을 동시에 catch (호출 + 참조). 한 fixture 가 *서로 다른 규칙 두 개를 동시에 검증* 하는 케이스 — 규칙별 1:1 fixture 가 아니어도 됨.
- `app-bootstrap` 의 test classpath 에 Jackson 이 없어서 컴파일 실패 → `testImplementation 'org.springframework.boot:spring-boot-starter-json'` 추가. *fitness function 자체에 의존성을 끌어들이는 cost* 가 있음을 의식해야 한다.
- 의견 / 해석 후보:
- 라이브러리 *버전* 차단 (jackson-databind ≥ 2.10) 은 supply-chain branch 의 책임이지만, *코드 사용 차단* (deprecated API 호출 금지) 은 boundary contract 의 책임. 두 가지를 같은 PR 에서 묶으면 책임 경계가 흐려진다.
- "CVE 가 알려진 후에는 사람이 review 로 막으면 된다" 는 흔한 반론은 *시간 경과에 따른 attention decay* 를 무시한다. 5년 뒤 합류한 신입이 PR review 할 때 `enableDefaultTyping` 이 안전한지 즉시 판단하기 어렵다 — fitness function 은 *지식 보존 비용* 의 외부화.
- Jackson 2.15 의 sealed type 자동 인식 같은 *조용한 행동 변화* 가 들어와도, 본 규칙은 호출 자체를 차단하므로 회귀 없음 — Jackson 의 mitigation 진화를 기다리는 대신 *진입점 자체를 봉쇄* 하는 전략의 정당화.
## Outline seed
1. CVE-2019-14379 의 한 줄 — `enableDefaultTyping()` + ehcache gadget 으로 RCE (CVSS 9.8).
2. Jackson 의 공식 대응 — 2.10 `@Deprecated` + `PolymorphicTypeValidator` + `BasicPolymorphicTypeValidator` allowlist.
3. 하지만 *우리 코드가 호출하지 않는다* 는 사실의 유지비용 — review fatigue, 시간 경과, 신입 합류.
4. fitness function 으로의 외부화 — ArchUnit 규칙 두 개 (`callMethodWhere` + `dependOnClassesThat`) 의 의도와 분리 이유.
5. violations-as-data 로 *규칙이 실제로 catch 하는지* 박기 — `DefaultTypingFixture` 한 메서드가 두 규칙을 동시에 검증.
6. fitness function 의 비용 — `spring-boot-starter-json` 을 test classpath 에 끌어들임.
7. 보안 책임의 경계 — *코드 사용 차단* (boundary contract) vs *버전 차단* (supply-chain) 의 분리.
8. 정리 — CVE 차단은 *지식 보존 비용* 의 코드화. fitness function 이 review 의 검토 부담을 commit 으로 이전한다.
## Canonical 전환 후보 / Canonical extraction candidates
- `wiki/projects/ca-tmpl/archunit-jackson-cve-block.md` 후보:
- 실제 두 규칙 + `DefaultTypingFixture` 의 코드 발췌.
- `testImplementation 'spring-boot-starter-json'` 추가의 비용.
- violations-as-data 1 fixture × 2 negative test 패턴.
- `wiki/concepts/fitness-function-for-known-cve.md` 후보:
- "*우리 코드가 호출하지 않는다*" 를 review 로 유지하는 비용 분석.
- 코드 사용 차단 vs 버전 차단의 책임 경계.
- 라이브러리 mitigation 진화와 *진입점 차단* 전략의 trade-off.
- 필요한 추가 검증:
- `BasicPolymorphicTypeValidator` 사용을 *권장* 하는 메시지를 ArchUnit 위반 메시지에 포함할 가치가 있는지 — false-positive 시 개발자가 즉시 대안을 알 수 있게.
- sealed `Command` 타입 도입 시 본 규칙이 `@JsonTypeInfo` 명시 패턴과 충돌하지 않는지 (충돌 없음 가설 — 검증은 future use case 에서).
## Sources / 근거 후보
- [[raw/branch-notes/feature-boundary-validation-mapping-contract]] — B5 결정 + 1차 enforcement 패스 결과.
- [[raw/official-docs/schema-jackson-polymorphic-deserialization]] — `JACK-POLY-C1..C5` (CVE, deprecated API, allowlist 표준).
- [[raw/blog-topics/archunit-violations-as-data-pattern-2026-05-28]] — violations-as-data 메타 패턴. 본 글감은 그 패턴의 *보안* 특화 사례.
- [[raw/branch-notes/feature-architecture-enforcement-rules]] — 같은 fitness-function 자체 검증 라인.
## 미해결 / Unknown
- 아직 확인해야 할 사실: violation message에 `BasicPolymorphicTypeValidator` 대안을 포함할지 여부.
- 과장하면 안 되는 부분: ArchUnit rule은 ca-tmpl 코드의 특정 호출/참조를 차단하는 것이며, Jackson RCE 일반 위험을 모두 제거한다고 쓰지 않는다.
## Related / 관련
- 관련 branch: [[raw/branch-notes/feature-boundary-validation-mapping-contract]]
- 관련 raw topic: [[raw/blog-topics/archunit-violations-as-data-pattern-2026-05-28]]
## Decision / 처리 결정
- 액션: `promote-to-canonical`
- 이유: `wiki/projects/ca-tmpl/boundary-validation-mapping.md` 에 Jackson default typing CVE static block 글감으로 반영했다.
- 다음 단계: source canonical이 `verified` 상태이므로 이후 `blogify` 대상으로 삼을 수 있다. 단 ArchUnit rule이 탐지 가능한 호출/참조 범위로 제한된다는 점을 유지한다.