
Offline-Checker für Thymeleaf CVE-2026-40477 / CVE-2026-41901 — zeigt dir, welcher der beiden CVSS-9.0-SSTI-Schwachstellen du ausgesetzt bist und ob deine Versionslinie überhaupt einen Fix hat (3.0.x: hat keinen).
Thymeleaf CVE-2026-40477 / CVE-2026-41901 Offline-Prüfwerkzeug —— keine Abhängigkeiten, ein einziges Jar, keine Netzwerkverbindung.
Zwei SSTI-Bypässe mit CVSS 9.0, innerhalb von neun Tagen zwei Fix-Versionen. Es beantwortet zuerst „Welche davon betreffen mich?“ und dann die unangenehmere Frage:
Gibt es für meine Versionslinie eine verfügbare Fix-Version?
Für 3.1.x ja (einfach auf 3.1.5.RELEASE aktualisieren).
Für 3.0.x und älter nein —— und genau das ist die Gruppe mit der größten Installationsbasis.
Der betroffene Bereich beider Advisories ist in OSV jeweils 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"}]}]
Das heißt, die gesamte 3.0-Linie ist enthalten, in der versionsweisen Auflistung sind 3.0.15.RELEASE bis hinunter zu 1.0.0 alle aufgeführt.
Auf Maven Central hingegen endet die 3.0-Linie bei 3.0.15.RELEASE, danach gibt es keine weiteren Releases:
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>
Die Fixversionen für beide CVEs liegen beide auf der 3.1-Linie. Daher haben 3.0.x-Nutzer nicht die Option „einfach die Versionsnummer ändern“, sondern nur die Migration über die große Versionslinie hinweg – und 3.1 ist eine offiziell ausdrücklich aufgeführte Breaking-Change-Version (Punkt für Punkt übernommen aus dem Abschnitt 3.1.0.M1 der offiziellen 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.…} 的,升上去会直接报错,这些取值得改由 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)。
Exit-Code: 2 = Für eine betroffene Version gibt es keine korrigierte Version in derselben Versionslinie · 1 = Betroffen, aber ein Upgrade innerhalb derselben Linie ist möglich / nicht beurteilbar · 0 = Nicht gefunden · 3 = Fehler bei Verwendung oder Pfad.
Kann direkt in die CI eingebunden werden.
Scannen Sie Build-Artefakte (target/*.jar, *.war), nicht das Quellcode-Verzeichnis.
Thymeleaf wird in den allermeisten Fällen transitiv durch spring-boot-starter-thymeleaf eingebracht, und der Starter selbst bringt keine Version mit –
in der pom ist die Thymeleaf-Version überhaupt nicht sichtbar. In diesem Fall sagt das Tool ausdrücklich „aus der pom nicht ermittelbar“, statt es als nicht vorhanden zu behandeln.
Drei Identifikationsgrundlagen, nach Zuverlässigkeit geordnet:
Implementation-Version im MANIFEST – auch wenn die jar von Repackaging-Tools umbenannt wurde, ist sie erkennbar.
(Im offiziellen Thymeleaf-jar gibt es unter META-INF/ nur MANIFEST.MF, kein maven/-Verzeichnis, daher ist dies für es die härteste Grundlage.)pom.propertiesBOOT-INF/lib/ und WEB-INF/lib/ in fat jar / war werden einzeln aufgeschlüsselt und geprüft, auch das MANIFEST eingebetteter jars wird gelesen.
CVE-2026-40477 | CVE-2026-41901 | |
|---|---|---|
| GHSA | GHSA-r4v4-5mwr-2fwr | GHSA-c9ph-gxww-7744 |
| CVSS | 9.0 | 9.0 |
| Betroffen | <= 3.1.3.RELEASE | <= 3.1.4.RELEASE |
| Behoben | 3.1.4.RELEASE | 3.1.5.RELEASE |
| Offengelegt | 2026-04-15 | 2026-05-04 |
| Offizielles Zitat | "fails to properly restrict the scope of accessible objects" | "fails to properly neutralize specific constructs", aufgetreten im sandboxed (restricted) Kontext |
Der betroffene Bereich des zweiten umfasst 3.1.4, daher fallen diejenigen, die gemäß der ersten Advisory auf 3.1.4 aktualisiert haben, in den zweiten.
Aber lesen Sie das nicht als „offiziell nicht sauber behoben“ – die beiden Advisories beschreiben unterschiedliche Mechanismen,
3.1.4 (2026-04-12) und 3.1.5 (2026-04-21) liegen neun Tage auseinander,
kein offizieller Text sagt, dass der vorherige Fix unvollständig war. Dieses Tool stellt nur Fakten nebeneinander und zieht diese Schlussfolgerung nicht für Sie.
Jede Zahl in RuleTable.java lässt sich nachträglich überprüfen:
python tools/gen_rules.py --show
Es gleicht die Bewertungstabelle mit zwei Primärquellen ab – den betroffenen Bereichen und der versionsweisen Liste von OSV sowie der maven-metadata.xml von Maven Central – und beendet sich mit einem Nicht-Null-Exit-Code, wenn sie nicht übereinstimmen.
Drei Vereinbarungen:
mvn package # JDK 17;target/thymeleaf-check-0.1.0.jar
mvn test # 19 个用例
Null Abhängigkeiten zur Laufzeit sind Absicht: Ein Diagnosewerkzeug muss in jede Umgebung geworfen werden können und sofort laufen.
Apache-2.0
| Code | Bedeutung |
|---|---|
0 | Scan abgeschlossen, und jede Datei wurde tatsächlich eingelesen, keine Funde, die eine Aktion erfordern |
4 | Eine Datei konnte nicht gelesen werden – kein Zip, abgeschnittener Inhalt oder Lesefehler |
🔴 4 wurde am 2026-09-09 hinzugefügt, und der Grund dafür verdient eine klare Erklärung.
Zuvor hinterließen nicht lesbare Dateien nur eine Hinweiszeile in der Ausgabe, während der Exit-Code weiterhin 0 war –
die Spur ist für Menschen gedacht, CI und Skripte schauen auf den Exit-Code, also bedeutete „ich konnte es nicht lesen" in der Automatisierung „bestanden".
Ein beschädigtes, verschlüsseltes oder unvollständig heruntergeladenes Jar wurde stillschweigend zu einem „keine Probleme gefunden".
„Ich kann es nicht lesen" und „du bist sicher" müssen zwei verschiedene Aussagen sein.
⚠️ Ein legitimes leeres Jar gilt nicht als nicht lesbar (ein 22-Byte-EOCD-Datensatz ist ein echtes leeres Zip) und löst kein 4 aus –
bei zu vielen Fehlalarmen schaut niemand mehr auf echte Warnungen.
Die Bedeutung der übrigen Exit-Codes siehe oben bei den einzelnen Bewertungsstufen und der Verwendungserklärung.