
ऑफ़लाइन चेकर Thymeleaf CVE-2026-40477 / CVE-2026-41901 के लिए — यह बताता है कि आप दो CVSS 9.0 SSTI खामियों में से किसके संपर्क में हैं, और क्या आपके वर्ज़न लाइन में कोई फिक्स मौजूद है (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 और उससे पुराने के लिए, नहीं है —— और वही वह समूह है जिसमें सबसे ज़्यादा इंस्टॉलेशन हैं।
दोनों advisory की प्रभावित सीमा, 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 全都列着।
而 Maven Central 上 3.0 线止于 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>
दोनों CVE के फिक्स्ड वर्ज़न 3.1 लाइन पर हैं। इसलिए 3.0.x उपयोगकर्ताओं के पास "बस वर्ज़न नंबर बदल दें" का विकल्प नहीं है,
केवल बड़ी वर्ज़न लाइन के पार माइग्रेट करने का विकल्प है — और 3.1 आधिकारिक रूप से सूचीबद्ध ब्रेकिंग चेंज है (आधिकारिक ChangeLog.txt के 3.1.0.M1 अनुभाग से शब्दशः उद्धृत):
- 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.…} 的,升上去会直接报错,这些取值得改由 Controller 放进 Model。
这是一次要排期的迁移,不是改个版本号。
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,比 3.1 线最高的 3.1.3 还高 36%,而它没有同线出路。
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 स्वयं संस्करण नहीं लाता ——
pom में Thymeleaf का संस्करण संख्या बिल्कुल दिखाई नहीं देती। ऐसी स्थिति में टूल स्पष्ट रूप से कहेगा "pom पढ़कर निर्धारित नहीं किया जा सकता", न कि इसे अनुपस्थित मान लेगा।
तीन पहचान आधार, विश्वसनीयता के क्रम में:
Implementation-Version —— jar को रीपैकेजिंग टूल द्वारा नाम बदलने पर भी पहचाना जा सकता है।
(Thymeleaf के आधिकारिक jar के META-INF/ के अंतर्गत केवल MANIFEST.MF है, maven/ डायरेक्टरी नहीं, इसलिए इसके लिए यह सबसे ठोस आधार है।)pom.propertiesfat jar / war के अंतर्गत BOOT-INF/lib/, WEB-INF/lib/ को अलग-अलग खोलकर देखा जाएगा, एम्बेडेड jar का 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 शामिल है, इसलिए जिन्होंने पहली advisory के अनुसार 3.1.4 तक अपग्रेड किया, वे दूसरे में आ जाते हैं।
लेकिन इसे "आधिकारिक रूप से पूरी तरह ठीक नहीं किया गया" के रूप में न पढ़ें —— दोनों advisory भिन्न तंत्रों का वर्णन करती हैं,
3.1.4 (2026-04-12) और 3.1.5 (2026-04-21) दो आधिकारिक संस्करणों में नौ दिन का अंतर है,
कोई भी आधिकारिक मूल पाठ यह नहीं कहता कि पहला सुधार अधूरा था। यह टूल केवल तथ्यों को साथ-साथ रखता है, आपके लिए यह निष्कर्ष नहीं निकालता।
RuleTable.java में प्रत्येक संख्या को वापस जाकर सत्यापित किया जा सकता है:
python tools/gen_rules.py --show
यह दो प्राथमिक स्रोतों — OSV की प्रभावित सीमाएँ और प्रति-संस्करण सूची, तथा Maven Central की
maven-metadata.xml — से निर्णय तालिका का मिलान करता है; मेल न खाने पर गैर-शून्य कोड के साथ बाहर निकलता है।
तीन नियम:
mvn package # JDK 17;target/thymeleaf-check-0.1.0.jar
mvn test # 19 个用例
रनटाइम शून्य निर्भरता जानबूझकर है: ट्रबलशूटिंग टूल को किसी भी वातावरण में सीधे चलाया जा सकना चाहिए।
Apache-2.0
| कोड | अर्थ |
|---|---|
0 | स्कैन पूरा हुआ, और हर फ़ाइल वास्तव में पढ़ी गई, ऐसी कोई खोज नहीं जिस पर आपको कार्रवाई करनी हो |
4 | कोई फ़ाइल पढ़ी नहीं जा सकी —— zip नहीं है, सामग्री कटी हुई है, या पढ़ने में विफलता |
🔴 4 को 2026-09-09 को जोड़ा गया था, और इसे जोड़ने का कारण स्पष्ट रूप से बताना ज़रूरी है।
इससे पहले, जो फ़ाइलें पढ़ी नहीं जा सकती थीं, उनके लिए आउटपुट में केवल एक पंक्ति का संकेत छोड़ा जाता था, और एक्ज़िट कोड पहले की तरह 0 ही रहता था ——
निशान इंसानों के देखने के लिए होता है, CI और स्क्रिप्ट एक्ज़िट कोड देखते हैं, इसलिए "मैं इसे पढ़ नहीं सका" स्वचालन में "पास" के बराबर हो जाता है।
एक भ्रष्ट, एन्क्रिप्टेड या अधूरी डाउनलोड हुई jar चुपचाप "कोई समस्या नहीं मिली" बन जाती है।
"मैं इसे पढ़ नहीं सकता" और "आप सुरक्षित हैं" दो अलग बातें होनी चाहिए।
⚠️ वैध खाली jar को पढ़ न पाना नहीं गिना जाता (22 बाइट का एक EOCD रिकॉर्ड एक वास्तविक खाली zip है), यह 4 को ट्रिगर नहीं करता ——
झूठे अलर्ट ज़्यादा होंगे तो असली अलर्ट कोई नहीं देखेगा।
शेष एक्ज़िट कोड के अर्थ ऊपर दिए गए विभिन्न निर्धारण स्तरों और उपयोग विवरण में देखें।