
org.pac4j:pac4j-jwt의 CVE-2026-29000(CVSS 10.0)에 대한 오프라인 스캐너입니다. jar/fat-jar를 직접 검사하므로 mvn dependency:tree가 작동하지 않는 환경에서도 동작합니다. 단일 jar, 의존성 없음, Java 8+.
CVE-2026-29000(CVSS 10.0) 오프라인 점검 —— 공식 advisory에 나열되지 않은 패키지까지 포함.
English | 中文
단일 jar, 약 24KB, 런타임 의존성 제로, Java 8 이상 사용 가능, 완전 오프라인, 어떤 데이터도 외부로 전송하지 않음.
org.pac4j:pac4j-jwt의 JwtAuthenticator는 **암호화된 JWT(JWE)**를 처리할 때 서명 검증을 강제하지 않습니다.
공격자가 서버의 RSA 공개키(공개키는 원래 공개됨)만 확보하면,
JWE로 감싼 PlainJWT를 구성하여 subject와 role을 임의의 값으로 작성하고,
임의의 사용자 신원으로 로그인할 수 있으며, 관리자까지 포함됩니다. 자격 증명이 전혀 필요 없습니다.
| 항목 | 값 |
|---|---|
| CVE | CVE-2026-29000 |
| GitHub advisory | GHSA-pm7g-w2cf-q238 |
| CVSS | 10.0(만점) |
| 공개일 | 2026-03-05 |
pac4j는 Spring Security, Apereo CAS, JEE, Vert.x, Play, Dropwizard 등에 광범위하게 통합되어 있습니다.
v0.1.0은 「공식 취약점 DB에는 1개 패키지만 나열되어 있지만 실제로는 5개다」라고 주장하며,
pac4j-oidc / javalin-pac4j / lagom-pac4j / ratpack-pac4j를 취약하다고 보고했습니다.
그것은 오탐입니다. 공식 advisory가 pac4j-jwt만 나열한 것이 맞습니다.
검증 근거(두 가지 독립적 증거, 모두 직접 재현 가능):
test / provided 의존성은 다운스트림으로 전달되지 않으며,
사용자의 runtime classpath에 pac4j-jwt가 나타나지 않습니다.pac4j-oidc-6.0.0.jar는 총 78개 항목이 모두 org/pac4j/oidc/ 아래에 있으며,
shade된 pac4j-jwt 클래스가 전혀 없습니다. 전이되지도 않고, 포함되지도 않습니다.무엇이 틀렸는가: v0.1.0은 pom을 하나씩 파싱했지만 「누가 pac4j-jwt 좌표를 작성했는가」만 보았고,
scope를 보지 않았습니다 —— 「pom에 작성됨」을 「사용자가 받게 됨」으로 착각한 것입니다.
v0.1.0의 보고 때문에 pac4j를 업그레이드했다면, 그 업그레이드는 필수가 아니었습니다(업그레이드 자체는 무해). 애플리케이션에 실제로 영향받는 버전의
pac4j-jwt가 존재할 때만 대응이 필요합니다.
특정 머신에 영향받는 pac4j-jwt가 있는지 판단할 때, mvn dependency:tree는 두 가지 상황에서 무력합니다 ——
프로덕션 머신에 패키징된 fat-jar만 있는 경우(소스와 pom 없음), 또는 어떤 SDK 내부에 shade되어
의존성 트리에 아예 나타나지 않는 경우. 이 도구는 아티팩트 자체를 직접 스캔하며, 빌드 환경에 의존하지 않습니다.
| 아티팩트 | 영향받는 버전 수 | 공식 advisory |
|---|---|---|
org.pac4j:pac4j-jwt | 114 | ✅ 유일하게 나열됨, 그리고 이것이 맞음 |
java -jar pac4j-check.jar ./myapp.jar # jar/war 하나 스캔
java -jar pac4j-check.jar /opt/apps # 디렉터리 스캔(재귀)
java -jar pac4j-check.jar /opt/apps --json # JSON 출력, 파이프 연결 용이
java -jar pac4j-check.jar ./app.jar --gbk # Windows 콘솔 한글 깨짐 시 사용
종료 코드: 0 = 영향받는 것 미발견 · 1 = 의문/판정 불가 · 2 = 영향받는 것 발견. CI에 바로 연결 가능.
[CRITICAL] pac4j-jwt 5.4.3
位置 :demo-app.jar!/BOOT-INF/lib/pac4j-jwt-5.4.3.jar
版本来源:pom.properties(可靠)
部署形态:Spring Boot fat-JAR
结论 :命中 CVE-2026-29000 —— JWE 处理路径未强制校验签名,
拿到服务器 RSA 公钥即可伪造任意身份(含管理员)登录
处置 :升级 pac4j-jwt 至 5.7.9
v0.1.0은 여기서
[CRITICAL] pac4j-oidc를 한 줄 더 보고했습니다 —— 그것은 오탐이며 v0.2.0에서 삭제되었습니다, 이유는 서두의 정정 설명을 참조하세요.
mvn dependency:tree로는 찾을 수 없는 유형판정은 일괄적으로 공식 advisory GHSA-pm7g-w2cf-q238을 기준으로 합니다:
pac4j-jwt < 4.5.9 -> 升 4.5.9
pac4j-jwt >= 5.0.0-RC1 且 < 5.7.9 -> 升 5.7.9
pac4j-jwt >= 6.0.4.1 且 < 6.3.3 -> 升 6.3.3
자체 검증: 이 도구는 Maven Central의 pac4j-jwt 전체 147개 버전에 대해 판정을 실행하여,
적중 수가 114로, 공식 advisory 세 구간의 버전 수 합(13+33+68)과 정확히 일치합니다.
이 단언은 테스트(OfficialRangeCrossCheckTest)에 작성되어 있으며, 맞지 않으면 빌드가 실패합니다.
⚠️ 하지만 이것이 검증하는 것이 무엇인지 분명히 해야 합니다: 이것은 버전 구간 알고리즘이 올바른지 검증하며, 「어떤 아티팩트가 판정표에 들어가야 하는가」는 검증하지 못합니다 —— v0.1.0의 오탐은 바로 후자에서 발생했고, 그때 이 자체 검증은 통과 상태였습니다. 검증이 통과한 범위 ≠ 결론이 성립하는 범위.
org.pac4j라는 하나의 groupId만 커버합니다.
제3자 연구는 영향받는 아티팩트가 총 19개, 1,020개 버전이라고 주장하지만 전체 목록을 공개하지 않았습니다.
이 도구가 독립적으로 재구성한 것은 org.pac4j 범위의 일부이며, 전체를 커버했다고 주장하지 않습니다.
다른 groupId(예: Apereo CAS의 org.apereo.cas)는 포함되지 않았습니다.
pac4j-jwt 6.0.0 ~ 6.0.4는 「의문」으로 표시하며 「영향받음」이 아닙니다.
공식 측은 6.x가 6.0.4.1부터 영향받는다고 밝혔고, 제3자 연구는 취약점이 이미 1.9.2에 도입되었다고 주장합니다 ——
사실이라면 이 5개 버전도 포함되어야 합니다. 우리는 제3자 결론을 독립적으로 검증하지 않았으므로,
별도로 표시하고 보수적 업그레이드를 권장하며, 직접 취약으로 판정하지 않습니다.
왜 이렇게 보수적인가: 판정 규칙이 틀리면 그것은 「오탐」이 아니라 사용자가 잘못된 행동을 하게 만드는 것입니다. 의문으로 표시할지언정, 검증되지 않은 범위를 결론으로 못 박지 않습니다.
mvn package # 산출물:target/pac4j-check.jar
mvn test # 31개 테스트
판정 오류, 누락 또는 오탐을 발견하면 Issue를 제출해 주세요. 재현 가능한 아티팩트 좌표(groupId:artifactId:version)를 제공해 주시면 훨씬 빠르게 수정할 수 있습니다.
Apache License 2.0
CVE-2026-29000(CVSS 10.0) 오프라인 스캐너 — 공식 advisory에 나열되지 않은 패키지까지 포함.
단일 jar, 약 24KB, 런타임 의존성 제로, Java 8 이상, 완전 오프라인, 어디에도 아무것도 전송하지 않음.
org.pac4j:pac4j-jwt의 JwtAuthenticator는 특정 암호화된 JWT(JWE) 처리 경로에서
서명 검증을 강제하지 않습니다. 서버의 RSA 공개키(설계상 공개됨)를 보유한 공격자는
임의의 subject와 role 클레임을 가진 JWE로 감싼 PlainJWT를 구성하여
자격 증명 없이 임의의 사용자, 관리자까지 포함하여 인증할 수 있습니다.
| CVE | CVE-2026-29000 |
| GitHub advisory | GHSA-pm7g-w2cf-q238 |
| CVSS | 10.0 |
| 공개일 | 2026-03-05 |
v0.1.0은 공식 advisory가 「패키지 하나만 나열했지만 실제로는 다섯 개다」라고 주장하며,
pac4j-oidc / javalin-pac4j / lagom-pac4j / ratpack-pac4j를 영향받는 것으로 표시했습니다.
그것은 오탐이었습니다. advisory가 pac4j-jwt만 나열한 것이 맞습니다.
두 가지 독립적 증거, 모두 재현 가능:
test / provided 의존성을 다운스트림 사용자에게 전달하지 않으므로,
pac4j-jwt는 그들의 runtime classpath에 결코 도달하지 않습니다.pac4j-oidc-6.0.0.jar는 78개 항목이 모두 org/pac4j/oidc/ 아래에 있으며,
shade된 pac4j-jwt 클래스가 없습니다.근본 원인: v0.1.0은 모든 pom을 파싱했지만 누가 좌표를 명명하는가만 보았고,
scope는 결코 보지 않았습니다 — 「pom에 선언됨」을 「사용자에게 도달함」으로 착각한 것입니다.
v0.1.0 보고 때문에 pac4j를 업그레이드했다면, 그 업그레이드는 필수가 아니었습니다(무해하기는 함). 영향받는
pac4j-jwt가 실제로 존재할 때만 대응이 필요합니다.
영향받는 pac4j-jwt가 특정 머신에 실제로 있는지 판단하는 것은 두 가지 흔한 경우에
mvn dependency:tree를 무력화합니다: 패키징된 fat-jar만 있는 프로덕션 박스(소스도 pom도 없음),
또는 어떤 벤더 SDK 내부에 shade되어 의존성 트리에 보이지 않는 복사본. 이 도구는 아티팩트 자체를 검사합니다.
| 아티팩트 | 영향받는 버전 | 공식 advisory |
|---|---|---|
org.pac4j:pac4j-jwt | 114 | ✅ 유일하게 나열됨 — 그리고 그것이 맞음 |
java -jar pac4j-check.jar ./myapp.jar
java -jar pac4j-check.jar /opt/apps
java -jar pac4j-check.jar /opt/apps --json
종료 코드: 0 깨끗함 · 1 의문/판정 불가 · 2 영향받음.
mvn dependency:tree가 볼 수 없는 경우판정은 공식 advisory GHSA-pm7g-w2cf-q238을 정확히 따릅니다:
pac4j-jwt < 4.5.9 -> 4.5.9
pac4j-jwt >= 5.0.0-RC1 and < 5.7.9 -> 5.7.9
pac4j-jwt >= 6.0.4.1 and < 6.3.3 -> 6.3.3
교차 검증: 공개된 pac4j-jwt 전체 147개 버전에 규칙을 실행하면 114개가 영향받음 — advisory의 세 구간(13+33+68)과 정확히 일치합니다. 이는 OfficialRangeCrossCheckTest에 단언되어 있으며, 불일치 시 빌드가 실패합니다.
두 가지 한계, 명확히 밝힘:
org.pac4j groupId만 커버합니다. 제3자 연구는 19개 영향받는 패키지, 1,020개 버전을 보고하지만 전체 목록을 공개하지 않았습니다. 이 도구는 org.pac4j 부분을 독립적으로 재구성하며 전체 커버리지를 주장하지 않습니다.6.0.4.1에서 시작하지만, 제3자 연구는 결함이 1.9.2만큼 일찍 도입되었다고 밝힙니다. 우리는 후자를 독립적으로 검증하지 않았으므로, 이 버전들은 취약하다고 단언하는 대신 보수적 업그레이드 권장과 함께 사람의 검토를 위해 표시됩니다.잘못된 판정은 「오탐」이 아닙니다 — 사람들이 잘못된 행동을 하게 만듭니다.
Apache License 2.0
이 도구가 답하는 것은 「내가 걸렸는가」입니다. 아래는 이 도구가 답할 수 없는 것들이며, 저에게 의뢰하실 수 있습니다:
📮 [email protected] —— 상황을 설명해 주시면 24시간 내에 한 페이지 분량의 서면 답변을 드립니다: 가능한지, 어디가 어려운지, 대략 얼마나 걸리는지. 이 단계는 무료이며, 먼저 무엇을 약속하실 필요도 없습니다.
| 아티팩트 | pac4j-jwt에 대한 의존 | 사용자에게 전달되는가 |
|---|
pac4j-oidc | test scope(3.0.0 / 4.0.0 / 4.5.0 / 5.0.0 / 5.7.0 / 6.0.0 / 6.3.0 버전별로 확인) | ❌ |
javalin-pac4j | test scope | ❌ |
lagom-pac4j-parent | provided scope | ❌ |
ratpack-pac4j:1.4.6 | 해당 의존 블록 전체가 XML 주석으로 감싸져 있어 존재하지 않음 | ❌ |
| 아티팩트 | pac4j-jwt 선언 방식 | 사용자에게 전달되는가 |
|---|
pac4j-oidc | test scope(3.0.0 / 4.0.0 / 4.5.0 / 5.0.0 / 5.7.0 / 6.0.0 / 6.3.0에서 확인) | ❌ |
javalin-pac4j | test scope | ❌ |
lagom-pac4j-parent | provided scope | ❌ |
ratpack-pac4j:1.4.6 | 블록 전체가 XML 주석 안에 있음 — 존재하지 않음 | ❌ |