العودة إلى التحديثات
New releaseSep 3, 2026

pac4j-check v0.2.0

ماسح ضوئي غير متصل لـ CVE-2026-29000 (CVSS 10.0) في org.pac4j:pac4j-jwt. يفحص ملفات jar/fat-jars مباشرةً، لذا يعمل حيث لا يستطيع mvn dependency:tree العمل. ملف jar واحد، بدون تبعيات، Java 8+.

مشاركة

pac4j-check

فحص دون اتصال بالإنترنت للثغرة CVE-2026-29000 (CVSS 10.0) —— بما في ذلك الحزم التي لم يدرجها التنبيه الرسمي.

English | 中文

ملف jar واحد، بحجم ~24KB، بدون أي تبعيات وقت التشغيل، يعمل بدءًا من Java 8، يعمل دون اتصال بالإنترنت بالكامل، ولا يرسل أي بيانات إلى أي مكان.


ما هي هذه الثغرة

لا يفرض JwtAuthenticator في org.pac4j:pac4j-jwt التحقق من التوقيع عند معالجة رموز JWT المشفّرة (JWE). يكفي أن يحصل المهاجم على المفتاح العام RSA للخادم (والمفتاح العام علني بطبيعته)، ليتمكن من إنشاء PlainJWT مغلّف داخل JWE، وكتابة قيمة subject والدور كما يشاء، والدخول بأي هوية مستخدم، بما في ذلك المدير. دون أي بيانات اعتماد.

البندالقيمة
CVECVE-2026-29000
GitHub advisoryGHSA-pm7g-w2cf-q238
CVSS10.0 (الدرجة الكاملة)
تاريخ النشر2026-03-05

يُدمج pac4j على نطاق واسع في Spring Security وApereo CAS وJEE وVert.x وPlay وDropwizard وغيرها.

🔴 تصحيح v0.2.0: الادعاء الجوهري في v0.1.0 كان خاطئًا

ادّعى v0.1.0 أن «قاعدة الثغرات الرسمية أدرجت حزمة واحدة فقط، بينما توجد فعليًا خمس حزم»، وبناءً على ذلك كان يُبلّغ عن pac4j-oidc / javalin-pac4j / lagom-pac4j / ratpack-pac4j كمتأثرة. كانت تلك إنذارات خاطئة. إدراج التنبيه الرسمي لـ pac4j-jwt فقط هو الصحيح.

أساس المراجعة (دليلان مستقلان، وكلاهما قابل لإعادة الإنتاج ذاتيًا):

المكوّنكيف يعلن اعتماده على pac4j-jwtهل ينتقل إلى المستخدمين
pac4j-oidcنطاق test (تم التحقق إصدارًا بإصدار: 3.0.0 / 4.0.0 / 4.5.0 / 5.0.0 / 5.7.0 / 6.0.0 / 6.3.0)
javalin-pac4jنطاق test
lagom-pac4j-parentنطاق provided
ratpack-pac4j:1.4.6كتلة الاعتماد تلك مغلّفة بالكامل داخل تعليق XML، فهي غير موجودة أصلًا
  1. النطاق لا ينتقل —— في Maven، اعتماديات test / provided لا تنتقل إلى المستهلكين downstream، فلن يظهر pac4j-jwt على runtime classpath الخاص بالمستخدمين.
  2. التحقق الفعلي من المكوّن —— يحتوي pac4j-oidc-6.0.0.jar على 78 مدخلًا، جميعها تحت org/pac4j/oidc/، ولا توجد أي أصناف pac4j-jwt مدمجة (shaded) بالداخل. فلا هو ينتقل، ولا هو محمول.

أين كان الخطأ: حلّل v0.1.0 كل ملف pom على حدة، لكنه نظر فقط إلى «من كتب الإحداثية pac4j-jwt»، ولم ينظر إلى scope —— فاعتبر «مكتوب في pom» بمنزلة «سيصل إلى المستخدم».

إذا كنت قد رقّيت pac4j بسبب تقرير v0.1.0، فذلك الترقية لم تكن ضرورية (والترقية نفسها غير ضارة). لا حاجة لأي إجراء إلا إذا كان pac4j-jwt بإصدار متأثر موجودًا فعلًا في تطبيقك.

لماذا ما زلنا بحاجة إلى أداة مخصصة

لتحديد ما إذا كان pac4j-jwt المتأثر موجودًا فعلًا على جهاز معيّن، يفشل mvn dependency:tree في حالتين —— إذ لا يوجد على جهاز الإنتاج سوى fat-jar جاهز (بلا مصدر ولا pom)؛ أو أنه مدمج (shaded) داخل أحد الـ SDK، فلا يظهر في شجرة الاعتماديات أصلًا. تفحص هذه الأداة المكوّن نفسه مباشرة، دون الاعتماد على بيئة البناء.

المكوّنعدد الإصدارات المتأثرةالتنبيه الرسمي
org.pac4j:pac4j-jwt114✅ الوحيد المُدرج، وهذا صحيح

الاستخدام

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، والسبب موضّح في تصحيح المقدمة.

ماذا تفعل

  • تفكيك Spring Boot fat-JAR بشكل تكراري (في الذاكرة، دون فك ضغط على القرص)، مع تتبّع المسار المتداخل المحدد
  • التعرّف على الحالات المدمجة (shaded) داخل jar المضيف —— وهي الحالة التي لا يستطيع mvn dependency:tree كشفها
  • تتبّع سلسلة الإدخال —— لتخبرك أي مكوّن جرّ pac4j-jwt إلى الداخل
  • إعطاء الحكم وهدف الترقية المحدد وفق النطاقات الرسمية

قواعد الحكم وحدوده (يُرجى قراءتها قبل الاستخدام)

يعتمد الحكم دائمًا على التنبيه الرسمي 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

التحقق الذاتي: شغّلت هذه الأداة الحكم على جميع إصدارات pac4j-jwt الـ 147 على Maven Central، فكان عدد الإصابات 114، وهو مطابق تمامًا لمجموع عدد الإصدارات في نطاقات التنبيه الرسمي الثلاثة (13+33+68). هذا التأكيد مكتوب في الاختبارات (OfficialRangeCrossCheckTest)، وأي عدم تطابق يُفشل البناء.

⚠️ لكن يجب أن تعرف ما الذي يتحقق منه هذا فعلًا: إنه يتحقق من صحة خوارزمية النطاقات الإصدارية، ولا يستطيع التحقق من «أي المكوّنات يجب أن تدخل جدول الحكم» —— فالإنذار الخاطئ في v0.1.0 حدث تحديدًا في الشق الثاني، بينما كان هذا التحقق الذاتي أخضر آنذاك. نطاق نجاح التحقق ≠ نطاق صحة الاستنتاج.

قيدان يجب توضيحهما

  1. يغطي فقط groupId واحدًا هو org.pac4j. هناك أبحاث من أطراف ثالثة تقول إن المكوّنات المتأثرة 19 مكوّنًا و1,020 إصدارًا، لكنها لم تنشر القائمة الكاملة. ما تعيد هذه الأداة بناءه بشكل مستقل هو الجزء الخاص بـ org.pac4j، ولا تدّعي تغطية الكل. لم تُدرَج groupIds أخرى (مثل org.apereo.cas الخاص بـ Apereo CAS).

  2. يُصنّف pac4j-jwt 6.0.0 ~ 6.0.4 كـ «محلّ شك» وليس «متأثر». تقول الجهة الرسمية إن 6.x متأثر بدءًا من 6.0.4.1؛ بينما تقول أبحاث طرف ثالث إن الثغرة أُدخلت منذ 1.9.2 —— وإن صحّ ذلك، فيجب احتساب هذه الإصدارات الخمسة أيضًا. لم نتحقق بشكل مستقل من استنتاج الطرف الثالث، لذلك نُبرزها منفصلة ونوصي بترقية تحوّطية، بدلًا من الحكم عليها بالخطورة مباشرة.

لماذا كل هذا التحوّط: خطأ قاعدة الحكم ليس «إنذارًا خاطئًا»، بل يدفع المستخدم إلى فعل خاطئ. نفضّل وسم الحالة كمحلّ شك على تثبيت نطاق غير مُتحقق منه كاستنتاج نهائي.

البناء

mvn package        # الناتج: target/pac4j-check.jar
mvn test           # 31 اختبارًا

الملاحظات

إذا وجدت خطأً في الحكم، أو إغفالًا، أو إنذارًا خاطئًا، يُرجى فتح Issue. وإذا أمكنك تقديم إحداثيات مكوّن قابلة لإعادة الإنتاج (groupId:artifactId:version)، فسيكون الإصلاح أسرع بكثير.

License

Apache License 2.0


pac4j-check (English)

Offline scanner for CVE-2026-29000 (CVSS 10.0) — including the packages the official advisory does not list.

Single jar, ~24KB, zero runtime dependencies, Java 8+, fully offline, sends nothing anywhere.

The vulnerability

JwtAuthenticator in org.pac4j:pac4j-jwt fails to enforce signature validation on certain encrypted JWT (JWE) processing paths. An attacker holding the server's RSA public key (which is public by design) can craft a JWE-wrapped PlainJWT with arbitrary subject and role claims and authenticate as any user, including administrators — with no credentials.

CVECVE-2026-29000
GitHub advisoryGHSA-pm7g-w2cf-q238
CVSS10.0
Published2026-03-05

🔴 v0.2.0 correction: v0.1.0's central claim was wrong

v0.1.0 claimed the official advisory "lists only one package while there are five", and flagged pac4j-oidc / javalin-pac4j / lagom-pac4j / ratpack-pac4j as affected. Those were false positives. The advisory listing only pac4j-jwt is correct.

ArtifactHow it declares pac4j-jwtReaches consumers?
pac4j-oidctest scope (verified on 3.0.0 / 4.0.0 / 4.5.0 / 5.0.0 / 5.7.0 / 6.0.0 / 6.3.0)
javalin-pac4jtest scope
lagom-pac4j-parentprovided scope
ratpack-pac4j:1.4.6the whole block is inside an XML comment — it does not exist

Two independent lines of evidence, both reproducible:

  1. Scope does not propagate — Maven does not pass test / provided dependencies to downstream consumers, so pac4j-jwt never reaches their runtime classpath.
  2. Artifact inspectionpac4j-oidc-6.0.0.jar has 78 entries, all under org/pac4j/oidc/, with no shaded pac4j-jwt classes.

Root cause: v0.1.0 did parse every pom, but only looked at who names the coordinate, never at scope — mistaking "declared in a pom" for "reaches the consumer".

If you upgraded pac4j because of a v0.1.0 report, that upgrade was not required (though harmless). Action is only needed when an affected pac4j-jwt is actually present.

Why a dedicated tool

Deciding whether an affected pac4j-jwt is actually on a given machine defeats mvn dependency:tree in two common cases: a production box with only a packaged fat-jar (no sources, no pom), or a copy shaded inside some vendor SDK, invisible to the dependency tree. This tool inspects the artifacts themselves.

ArtifactAffected versionsIn official advisory
org.pac4j:pac4j-jwt114✅ the only one listed — and that is correct

Usage

java -jar pac4j-check.jar ./myapp.jar
java -jar pac4j-check.jar /opt/apps
java -jar pac4j-check.jar /opt/apps --json

Exit codes: 0 clean · 1 disputed/undetermined · 2 affected.

What it does

  • Recursively unpacks Spring Boot fat-JARs in memory (nothing written to disk)
  • Detects pac4j-jwt shaded into a host jar — the case mvn dependency:tree cannot see
  • Traces the introduction chain, so you know which artifact pulled it in
  • Reports a concrete upgrade target

Rules and limitations

Verdicts follow the official advisory GHSA-pm7g-w2cf-q238 exactly:

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

Cross-check: running the rules over all 147 published pac4j-jwt versions yields 114 affected — exactly matching the advisory's three ranges (13+33+68). This is asserted in OfficialRangeCrossCheckTest; a mismatch fails the build.

Two limitations, stated plainly:

  1. Only the org.pac4j groupId is covered. Third-party research reports 19 affected packages across 1,020 versions but has not published the full list. This tool independently reconstructs the org.pac4j portion and does not claim full coverage.
  2. pac4j-jwt 6.0.0–6.0.4 are reported as DISPUTED, not AFFECTED. The advisory starts the 6.x range at 6.0.4.1; third-party research states the flaw was introduced as early as 1.9.2. We have not independently verified the latter, so these versions are flagged for human review with a conservative upgrade recommendation rather than asserted as vulnerable.

A wrong verdict is not a "false positive" — it makes people take the wrong action.

License

Apache License 2.0


هل تحتاج إلى فحص أكثر تعمقًا؟

هذه الأداة تجيب على سؤال «هل أنا مصاب أم لا». أما ما يلي فهي لا تستطيع الإجابة عليه، ويمكنك التواصل معي للقيام به:

  • الاعتماديات مدمجة (shaded) أو مُعاد توجيهها (relocate)، أو تعذّر الحصول على ناتج البناء أصلًا
  • المطلوب الحكم على «هل ستُفعَّل هذه الثغرة فعلًا على سلسلة الاستدعاء لدينا»، وليس مجرد مطابقة الإصدار
  • الحاجة إلى تخصيص وفق عملية البناء أو بيئة الشبكة الداخلية لديكم، ودمجها في خط الأنابيب الحالي
  • لديك مشكلة من النوع نفسه في مكوّن آخر، ولا توجد أداة جاهزة بعد

📮 [email protected] —— اشرح الحالة، وسأعطيك ردًا مكتوبًا في صفحة واحدة خلال 24 ساعة: هل يمكن القيام به، وأين الصعوبة، وكم يستغرق تقريبًا. هذه الخطوة مجانية، ولا تتطلب منك أي التزام مسبق.

الفئات