
أداة فحص دون اتصال بالإنترنت لثغرات Thymeleaf CVE-2026-40477 / CVE-2026-41901 — تُخبرك بأيٍّ من ثغرتي SSTI بدرجة خطورة CVSS 9.0 أنت معرّض لها، وما إذا كان إصدارك يتضمن إصلاحًا على الإطلاق (3.0.x: لا يتضمن).
أداة فحص محلية لثغرات Thymeleaf CVE-2026-40477 / CVE-2026-41901 — بدون تبعيات، ملف jar واحد، بدون اتصال بالإنترنت.
ثغرتان بتقييم CVSS 9.0 لتجاوز قوالب SSTI، صدر لهما إصداران إصلاحيان خلال تسعة أيام. الأداة تجيب أولاً على «أي من الثغرتين أصابتني»، ثم تجيب على السؤال الأكثر إزعاجاً:
في خط الإصدارات الخاص بي، هل يوجد إصدار إصلاحي يمكن الترقية إليه؟
بالنسبة لـ 3.1.x، نعم (الترقية إلى 3.1.5.RELEASE كافية).
بالنسبة لـ 3.0.x والإصدارات الأقدم، لا — وهذه هي الفئة الأوسع انتشاراً في الأنظمة.
نطاق التأثير للثغرتين في OSV هو introduced: 0:
curl -s https://api.osv.dev/v1/vulns/GHSA-r4v4-5mwr-2fwr | jq '.affected[0].ranges'
# [{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.4.RELEASE"}]}]
أي أن خط 3.0 بأكمله متأثر، وقائمة الإصدارات التفصيلية تبدأ من 3.0.15.RELEASE وصولاً إلى 1.0.0.
بينما خط 3.0 على Maven Central يتوقف عند 3.0.15.RELEASE، ولا توجد إصدارات بعده:
curl -s https://repo1.maven.org/maven2/org/thymeleaf/thymeleaf/maven-metadata.xml \
| grep -o '<version>3\.0\.[^<]*</version>' | tail -1
# <version>3.0.15.RELEASE</version>
الإصدارات الإصلاحية للثغرتين تقعان في خط 3.1. لذا لا يملك مستخدمو 3.0.x خيار «تغيير رقم الإصدار»،
بل فقط الانتقال عبر خط إصدارات رئيسي — و3.1 مُدرج رسمياً كتغيير جذري (مقتبس حرفياً من قسم 3.1.0.M1 في ChangeLog.txt الرسمي):
- Removed web-API based expression security objects (#request, #response, #session, #servletContext).
- Removed support for Spring 3.x and Spring 4.x.
- Set minimum JDK compatibility level to JDK 8 project-wide (JDK 17 for thymeleaf-spring6).
القالب الذي كتب فيه ${#request.…} / ${#session.…} سيفشل مباشرة بعد الترقية، ويجب نقل هذه القيم إلى Model عبر Controller.
هذا ترحيل يحتاج إلى جدولة، وليس مجرد تغيير رقم إصدار.
عدد التبعيات من deps.dev (قراءة مباشرة بتاريخ 2026-09-04، يمكن لأي شخص إعادة الحساب):
| الإصدار | عدد التبعيات | أي الثغرتين أصابتاه | هل يمكن الترقية ضمن نفس الخط |
|---|---|---|---|
| 3.0.11.RELEASE | 1124 | الثغرتان | ❌ لا يوجد إصلاح في خط 3.0 |
| 3.0.15.RELEASE | 678 | الثغرتان | ❌ نفسه أعلاه، وهو نهاية الخط |
| 3.0.12.RELEASE | 641 | الثغرتان | ❌ |
| 3.1.3.RELEASE | 826 | الثغرتان | ✅ الترقية إلى 3.1.5 |
| 3.1.2.RELEASE | 677 | الثغرتان | ✅ |
| 3.1.4.RELEASE | 70 | فقط CVE-2026-41901 | ✅ |
| 3.1.5.RELEASE | 590 | — | آمن بالفعل |
الإصدار الأوسع انتشاراً هو 3.0.11.RELEASE، وهو أعلى بنسبة 36% من أعلى إصدار في خط 3.1 (3.1.3)، ولا يوجد له مخرج ضمن نفس الخط.
java -jar thymeleaf-check.jar <مسار مجلد أو jar/war> [--utf8|--gbk]
$ java -jar thymeleaf-check.jar ./target
[CRITICAL] ./target/myapp.war :: BOOT-INF/lib/thymeleaf-3.0.11.RELEASE.jar
المكوّن:thymeleaf الإصدار 3.0.11.RELEASE (خط 3.0، المصدر: MANIFEST(Implementation-Version))
الإصابة: CVE-2026-40477 + CVE-2026-41901
متأثر، ولا يوجد أي إصدار إصلاحي لخط 3.0 على Maven Central (الخط يتوقف عند 3.0.15.RELEASE).
رمز الخروج: 2 = يوجد مكوّن في خط إصدارات بلا إصلاح ضمن نفس الخط · 1 = متأثر لكن يمكن الترقية ضمن نفس الخط / غير قابل للتحديد · 0 = لم يُعثر على شيء · 3 = خطأ في الاستخدام أو المسار.
يمكن ربطه مباشرة في CI.
افحص نواتج البناء (target/*.jar، *.war)، ولا تفحص مجلدات المصدر.
Thymeleaf في الغالب يُجلب كتبعية غير مباشرة عبر spring-boot-starter-thymeleaf، والـ starter لا يحمل رقم إصدار —
لن ترى رقم إصدار Thymeleaf في ملف pom. في هذه الحالة ستوضح الأداة صراحة «تعذّر التحديد من pom»، بدلاً من تجاهله.
ثلاثة مصادر للتعريف، مرتبة حسب الموثوقية:
Implementation-Version في MANIFEST — يتعرف على الجرة حتى لو غُيّر اسمها بواسطة أدوات إعادة التغليف.
(جرة Thymeleaf الرسمية تحتوي في META-INF/ على MANIFEST.MF فقط، بدون مجلد maven/، لذا فهذا هو المصدر الأقوى لها.)pom.propertiesمجلدا BOOT-INF/lib/ و WEB-INF/lib/ داخل fat jar / war يُفحصان ملفاً بملف، ويُقرأ MANIFEST للجرار المدمجة أيضاً.
CVE-2026-40477 | CVE-2026-41901 | |
|---|---|---|
| GHSA | GHSA-r4v4-5mwr-2fwr | GHSA-c9ph-gxww-7744 |
| CVSS | 9.0 | 9.0 |
| المتأثر | <= 3.1.3.RELEASE | <= 3.1.4.RELEASE |
| الإصلاح | 3.1.4.RELEASE | 3.1.5.RELEASE |
| الإفصاح | 2026-04-15 | 2026-05-04 |
| النص الرسمي | "fails to properly restrict the scope of accessible objects" | "fails to properly neutralize specific constructs"، يحدث في سياق sandboxed (restricted) |
نطاق تأثير الثانية يشمل 3.1.4، لذا من رقّى إلى 3.1.4 وفقاً لتحذير الأولى يقع ضمن نطاق الثانية.
لكن لا تقرأ هذا كأنه «الإصلاح الرسمي لم يكتمل» — الثغرتان تصفان آليتين مختلفتين،
والإصداران الرسميان 3.1.4 (2026-04-12) و 3.1.5 (2026-04-21) يفصل بينهما تسعة أيام،
ولا يوجد أي نص رسمي يقول إن الإصلاح الأول ناقص. هذه الأداة تعرض الحقائق جنباً إلى جنب فقط، ولا تستنتج نيابة عنك.
كل رقم في RuleTable.java يمكن التحقق منه:
python tools/gen_rules.py --show
يتحقق من جدول التحديد مقابل مصدرين أساسيين — نطاقات التأثير وقوائم الإصدارات التفصيلية من OSV، و
maven-metadata.xml من Maven Central — وإذا لم يتطابقا يخرج برمز غير صفري.
ثلاثة مبادئ:
mvn package # JDK 17;target/thymeleaf-check-0.1.0.jar
mvn test # 19 حالة اختبار
عدم وجود تبعيات وقت التشغيل مقصود: يجب أن تعمل أداة الفحص في أي بيئة تُلقى فيها مباشرة.
Apache-2.0