Skip to main content

No entres en pánico: la inyección de plantillas de Thymeleaf solo te afecta si lo permites (CVE-2026-40478)

Escrito por

29 de abril de 2026

0 minutos de lectura

La vulnerabilidad de Thymeleaf con una puntuación CVSS de 9.1 llama la atención, como debería. Pero antes de llamar a la caballería y decir que es el nuevo Log4Shell, lee esto primero.

CVE-2026-40478 es una vulnerabilidad de inyección de plantillas del lado del servidor en Thymeleaf descubierta por el pentester Dawid Bakaj. Thymeleaf es un motor de plantillas para Java que se usa para renderizar páginas web del lado del servidor. El sandbox que normalmente impide la ejecución arbitraria de código se eludió mediante un carácter de tabulación. Y sí, si se explota, esto puede permitir la ejecución remota de código.

Pero esto es lo más importante: esta vulnerabilidad solo se aplica si tu código ya está haciendo algo que no debería.

Contra qué protege el sandbox

Thymeleaf tiene un sandbox de seguridad. Limita lo que pueden hacer las expresiones SpEL (Spring Expression Language) al evaluar contenido dinámico. El sandbox existe para una situación específica: cuando la entrada controlada por el usuario llega de alguna manera al motor de expresiones de Thymeleaf.

Si eso nunca ocurre en tu código, el sandbox nunca interviene y este CVE no te afecta. La forma correcta de usar Thymeleaf es sencilla: la entrada del usuario se incorpora al modelo de datos. La plantilla permanece estática la mayor parte del tiempo, en un archivo HTML.

Código Java:

@GetMapping("/greet/safe")
public String greetSafe(@RequestParam String name, Model model) {
   model.addAttribute("name", name);
   return "greet";
}

Plantilla de Thymeleaf:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<body>
   <p th:text="${name}">Default name</p>
</body>
</html>

Thymeleaf renderiza el valor de name. Nunca lo analiza como una expresión. Un atacante puede enviar cualquier carga útil como name, y no sucede nada interesante. Así está diseñado. Así es como se supone que debe funcionar Thymeleaf.

Uso indebido del motor de plantillas

La vulnerabilidad se puede explotar cuando un desarrollador permite que la entrada del usuario llegue directamente al motor de expresiones. Si esto ocurre, significa que está usando el framework de forma indebida. Aunque es posible, resulta bastante difícil lograrlo, sobre todo al usar Thymeleaf con Spring Boot.

@ResponseBody
@GetMapping("/greet/unsafe")
public String greetUnsafe(@RequestParam String name, Model model) {
   Context context = new Context();
   SpringTemplateEngine templateEngine = new SpringTemplateEngine();
   templateEngine.setTemplateResolver(new StringTemplateResolver());
   context.setVariable(name, name);
   String template = "<p th:text=\"'Hello ' + ${"+ name + "}\">...</p>";
   return templateEngine.process(template, context);
}

Como se muestra en el código anterior, tengo que crear manualmente una nueva instancia de <code>templateEngine</code> y configurar un resolver. Algo que normalmente proporciona Spring.
Además, tengo que establecer la variable en el contexto para que funcione mi caso de uso habitual y legítimo.

Sin embargo, en el caso anterior, la entrada del usuario se pasa al motor de expresiones. Ese es el requisito previo para que este CVE sea relevante.

Un patrón de uso indebido similar es la resolución dinámica de vistas. En lugar de crear directamente cadenas de plantilla, un desarrollador podría resolver las vistas a partir de la entrada del usuario:

@GetMapping("/page/unsafe")
@ResponseBody
public String showPageUnsafe(@RequestParam String page) {
   Context context = new Context();
   SpringTemplateEngine templateEngine = new SpringTemplateEngine();
   StringTemplateResolver resolver = new StringTemplateResolver();
   resolver.setTemplateMode(TemplateMode.TEXT);
   templateEngine.setTemplateResolver(resolver);
   context.setVariable(page, page);
   String template = "[[${" + page + "}]]";
   return templateEngine.process(template, context);
}

El caso de uso es legítimo: un endpoint sirve varias páginas. Pero ahora la entrada del usuario influye en lo que analiza Thymeleaf. Es el mismo patrón de uso indebido y con la misma posibilidad de explotación. Fíjate de nuevo en toda la configuración manual que se necesita para llegar hasta aquí. La versión segura sigue teniendo solo tres líneas.

@GetMapping("/page/safe")
public String showPageSafe(@RequestParam String page) {
   return page;
}

Cómo el carácter de tabulación elude el sandbox de Thymeleaf

Una vez establecido un patrón de uso indebido, explotar la vulnerabilidad es sencillo.

El sandbox busca <code>new </code> (la palabra clave seguida de un espacio) para bloquear la instanciación de objetos. La técnica de evasión envía new[TAB] en su lugar. La comprobación previa no encuentra <code>new</code>, así que la deja pasar. Sin embargo, SpEL considera que la tabulación es un espacio en blanco válido y la analiza correctamente.

La carga útil se ve así:

new[TAB]org.springframework.core.io.FileSystemResource('shell.jsp').getOutputStream()

Después de comprobar la palabra clave, se aplica una lista de bloqueo de tipos que impide el uso de clases java.*. Sin embargo, las clases de Spring no estaban incluidas en esta lista. Como resultado, la lista de bloqueo incompleta, combinada con un filtro débil para <code>new</code>, permitió cargar clases como FileSystemResource. Esto hizo que se escribiera un archivo en el disco. En teoría, esto permite que un atacante deje un archivo JSP que invoque ProcessBuilder y ejecute código de forma remota.

Dos defensas fallaron de forma independiente: un problema con los espacios en blanco en la comprobación de palabras clave y una lista de bloqueo limitada. La evasión tuvo éxito porque las comprobaciones no contemplaban todos los separadores posibles. EndorLabs ofrece un análisis más detallado de la explotación, por si te interesa.

Visita el repositorio de GitHub para ver ejemplos funcionales del código seguro y del inseguro.

Qué debes hacer

Primero, aplica el parche. Actualiza a Thymeleaf 3.1.4, independientemente de si crees que tu código está afectado. No esperes los resultados de la auditoría.

Si usas Thymeleaf a través de Spring Boot, simplemente actualiza el parent starter de Spring Boot a la versión más reciente (actualmente, 3.5.14 o 4.0.6). Si resulta que tienes varias versiones de retraso, puedes revisar las recetas de OpenRewrite para migrar a la versión más reciente de Spring Boot 3.5 o Spring Boot 4.0.

Después de actualizar, revisa si tu código genera cadenas de plantilla o resuelve páginas de forma dinámica a partir de la entrada del usuario, pasándola directamente al motor de plantillas. Si es así, se trata de un patrón de uso indebido. Corrige el código, no solo la versión de la biblioteca.

La puntuación CVSS de 9.1 es real, pero condicional

Una puntuación CVSS crítica parte de la premisa de que se cumple el requisito previo. Si tu código envía entradas del usuario al motor de expresiones de Thymeleaf, una puntuación de 9.1 es correcta y el impacto es grave. Si no lo hace, el CVE en sí no te afecta. Sin embargo, ¡debes aplicar el parche de todos modos!

La pregunta que debes hacerle a tu equipo durante la auditoría no es solo «¿qué versión de Thymeleaf usamos?». También es «¿construimos dinámicamente nombres de vista o expresiones de plantilla a partir de datos de las solicitudes?»

Actualiza Thymeleaf a la versión 3.1.4 o posterior y luego responde esa segunda pregunta. Sea cual sea la respuesta, sigue analizando tus dependencias durante el desarrollo y monitoreándolas en producción con Snyk Open Source. Lo mejor es que puedes empezar gratis.

Empieza a proteger tus aplicaciones de Python

Encuentra y corrige vulnerabilidades en Python gratis con Snyk.

No se requiere tarjeta de crédito.

O regístrate con Azure AD Docker ID Bitbucket

Al usar Snyk, aceptas cumplir nuestras políticas, incluidos nuestros Términos del servicio y nuestra Política de privacidad.

Leer más

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Por qué los agentes de programación con IA siguen generando fallas de control de acceso

Los agentes de programación con IA pueden generar lógica de autorización que compila y supera la revisión, pero expone los datos de un inquilino a otro. Descubre por qué es difícil detectar el control de acceso roto y cómo prevenirlo.