
Comprobador offline para Thymeleaf CVE-2026-40477 / CVE-2026-41901: te indica a cuál de las dos vulnerabilidades SSTI con CVSS 9.0 estás expuesto y si tu línea de versión tiene alguna corrección (3.0.x: no la tiene).
Herramienta de diagnóstico offline para CVE-2026-40477 / CVE-2026-41901 de Thymeleaf —— sin dependencias, un solo jar, sin conexión a red.
Dos bypass de SSTI con CVSS 9.0, con dos versiones de corrección publicadas en nueve días. Primero responde «cuáles de estas me afectan», y luego responde la pregunta más incómoda:
¿Hay alguna versión corregida a la que pueda actualizar en mi línea de versiones?
Para 3.1.x, sí (basta con actualizar a 3.1.5.RELEASE).
Para 3.0.x y anteriores, no —— y ese es precisamente el grupo con mayor base instalada.
El rango afectado de ambas advisories, en OSV, es introduced: 0 en ambos casos:
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"}]}]
Es decir, toda la línea 3.0 está incluida, y en el listado versión por versión aparecen desde 3.0.15.RELEASE hasta 1.0.0.
Sin embargo, en Maven Central la línea 3.0 termina en 3.0.15.RELEASE, y después de eso no hay más publicaciones:
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>
Las versiones corregidas de ambas CVE están en la línea 3.1. Por lo tanto, los usuarios de 3.0.x no tienen la opción de «cambiar el número de versión»,
solo la migración a través de la línea de versión mayor — y 3.1 es un cambio disruptivo listado explícitamente por la documentación oficial (copiado punto por punto del segmento 3.1.0.M1 del ChangeLog.txt oficial):
- 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).
Las plantillas que hayan escrito ${#request.…} / ${#session.…} fallarán directamente al actualizar; esos valores deberán ser colocados en el Model por el Controller.
Esta es una migración que requiere planificación, no es solo cambiar un número de versión.
Número de dependencias de deps.dev (lectura directa del 2026-09-04, cualquiera puede recalcularlo):
| Versión | Número de dependencias | Cuáles afectan | ¿Se puede actualizar en la misma línea? |
|---|---|---|---|
| 3.0.11.RELEASE | 1124 | dos | ❌ La línea 3.0 no tiene versión con corrección |
| 3.0.15.RELEASE | 678 | dos | ❌ Igual que arriba, y ya es el final de esa línea |
| 3.0.12.RELEASE | 641 | dos | ❌ |
| 3.1.3.RELEASE | 826 | dos | ✅ Actualizar a 3.1.5 |
| 3.1.2.RELEASE | 677 | dos | ✅ |
| 3.1.4.RELEASE | 70 | solo afecta a CVE-2026-41901 | ✅ |
| 3.1.5.RELEASE | 590 | — | Ya es seguro |
La versión individual con mayor base instalada es 3.0.11.RELEASE, un 36% más que la 3.1.3, la más alta de la línea 3.1, y no tiene salida dentro de su misma línea.
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)。
Código de salida: 2 = hay componentes cuya línea de versión no tiene una versión corregida en la misma línea · 1 = afectado pero se puede actualizar dentro de la misma línea / no se puede determinar · 0 = no detectado · 3 = error de uso o de ruta.
Se puede integrar directamente en CI.
Escanear los artefactos de compilación (target/*.jar, *.war), no el directorio de código fuente.
En la gran mayoría de los casos, Thymeleaf se introduce de forma transitiva mediante spring-boot-starter-thymeleaf, y el starter en sí no incluye versión —
en el pom no se ve en absoluto el número de versión de Thymeleaf. En este caso, la herramienta indicará explícitamente «no se puede determinar leyendo el pom», en lugar de asumir que no existe.
Tres criterios de identificación, ordenados por fiabilidad:
Implementation-Version del MANIFEST — se reconoce incluso si la herramienta de reempaquetado cambió el nombre del jar.
(En el jar oficial de Thymeleaf, bajo META-INF/ solo hay MANIFEST.MF, no hay directorio maven/, por lo que para él este es el criterio más sólido.)pom.propertiesLos directorios BOOT-INF/lib/ y WEB-INF/lib/ dentro de un fat jar / war se abren y examinan uno por uno, y también se lee el MANIFEST de los jars embebidos.
CVE-2026-40477 | CVE-2026-41901 | |
|---|---|---|
| GHSA | GHSA-r4v4-5mwr-2fwr | GHSA-c9ph-gxww-7744 |
| CVSS | 9.0 | 9.0 |
| Afectado | <= 3.1.3.RELEASE | <= 3.1.4.RELEASE |
| Corrección | 3.1.4.RELEASE | 3.1.5.RELEASE |
| Divulgación | 2026-04-15 | 2026-05-04 |
| Frase oficial original | "fails to properly restrict the scope of accessible objects" | "fails to properly neutralize specific constructs", ocurre en un contexto sandboxed (restringido) |
El rango afectado de la segunda incluye 3.1.4, por lo que quienes actualizaron a 3.1.4 siguiendo el primer advisory quedan dentro de la segunda.
Pero no lo interpretes como «el oficial no lo corrigió del todo» — los dos advisories describen mecanismos diferentes,
3.1.4 (2026-04-12) y 3.1.5 (2026-04-21) son dos versiones oficiales separadas por nueve días,
y ningún texto oficial afirma que la corrección anterior fuera incompleta. Esta herramienta solo presenta los hechos uno al lado del otro, no saca esa conclusión por ti.
Cada número en RuleTable.java se puede verificar retrospectivamente:
python tools/gen_rules.py --show
Lo verifica contra dos fuentes primarias: los rangos afectados y la lista versión por versión de OSV, y el maven-metadata.xml de Maven Central; si no coinciden, sale con un código distinto de cero.
Tres convenciones:
mvn package # JDK 17;target/thymeleaf-check-0.1.0.jar
mvn test # 19 个用例
La ausencia de dependencias en tiempo de ejecución es intencional: una herramienta de diagnóstico debe poder ejecutarse directamente en cualquier entorno.
Apache-2.0
| Código | Significado |
|---|---|
0 | El escaneo terminó y cada archivo se leyó realmente, sin hallazgos que requieran tu acción |
4 | Hay archivos que no se pueden leer — no es un zip, contenido truncado o fallo de lectura |
🔴 El código 4 se añadió el 2026-09-09, y la razón merece explicarse.
Antes de eso, los archivos ilegibles solo dejaban una línea de aviso en la salida, y el código de salida seguía siendo 0 —
el rastro es para que lo vean las personas, pero CI y los scripts miran el código de salida, así que «no pude leerlo» equivale a «aprobado» en la automatización.
Un jar corrupto, cifrado o descargado de forma incompleta se convierte silenciosamente en un «no se encontraron problemas».
«No puedo leerlo» y «estás a salvo» deben ser dos frases distintas.