Skip to main content

Não entre em pânico: a injeção de template do Thymeleaf só causa danos se você permitir (CVE-2026-40478)

Escrito por

29 de abril de 2026

0 minutos de leitura

A vulnerabilidade do Thymeleaf, com pontuação CVSS 9.1, chama a atenção — e com razão. Mas, antes de convocar reforços e dizer que este é o novo Log4shell, leia isto primeiro.

CVE-2026-40478 é uma vulnerabilidade de injeção de template no lado do servidor do Thymeleaf, descoberta pelo pentester Dawid Bakaj. Thymeleaf é um mecanismo de templates em Java usado para renderizar páginas da web no lado do servidor. O sandbox que normalmente impede a execução arbitrária de código foi contornado usando um caractere de tabulação. E sim, isso pode levar à execução remota de código se a vulnerabilidade for explorada.

Mas aqui está o ponto mais importante: esta vulnerabilidade só se aplica se seu código já estiver fazendo algo que não deveria.

O que o sandbox protege

O Thymeleaf tem um sandbox de segurança. Ele limita o que expressões SpEL (Spring Expression Language) podem fazer ao avaliar conteúdo dinâmico. O sandbox existe para uma situação específica: quando uma entrada controlada pelo usuário chega, de alguma forma, ao mecanismo de expressões do Thymeleaf.

Se isso nunca acontece no seu código, o sandbox nunca é acionado, e esta CVE não afeta você. A forma correta de usar o Thymeleaf é simples: a entrada do usuário vai para o modelo de dados. Na maior parte do tempo, o template permanece estático em um arquivo HTML.

Código Java:

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

Template do Thymeleaf:

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

O Thymeleaf renderiza o valor de name. Ele nunca o interpreta como uma expressão. Um invasor pode enviar qualquer payload que quiser como name, e nada de interessante acontece. Esse é o design. É assim que o Thymeleaf deve funcionar.

Explorando o mecanismo de templates

A vulnerabilidade pode ser explorada quando um desenvolvedor permite que a entrada do usuário chegue diretamente ao mecanismo de expressões. Se isso acontece, é sinal de que o framework está sendo usado de forma indevida. Embora seja possível, é bem difícil chegar a esse ponto, especialmente ao usar o Thymeleaf com 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 mostrado no código acima, preciso criar manualmente uma nova instância de templateEngine e definir um resolver. Normalmente, o Spring fornece isso.
Além disso, preciso definir a variável no contexto para que meu caso de uso normal e legítimo funcione.

No entanto, no exemplo acima, a entrada do usuário é passada ao mecanismo de expressões. Esse é o pré-requisito para que esta CVE seja relevante.

Um padrão de uso indevido semelhante é a resolução dinâmica de views. Em vez de criar strings de template diretamente, um desenvolvedor pode resolver views com base na entrada do usuário:

@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);
}

O caso de uso é legítimo: um endpoint atende a várias páginas. Mas agora a entrada do usuário influencia o que o Thymeleaf interpreta. É o mesmo padrão de uso indevido, com a mesma possibilidade de exploração. Repare, mais uma vez, em todo o trabalho manual necessário para chegar a esse ponto. A versão segura continua tendo apenas três linhas.

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

Como o caractere de tabulação contorna o sandbox do Thymeleaf

Quando o padrão de uso indevido está presente, a exploração propriamente dita é simples.

O sandbox procura por new (a palavra-chave seguida de um espaço) para bloquear a instanciação de objetos. O bypass usa new[TAB]. A verificação preliminar não encontra new, então a expressão passa. Já o SpEL aceita a tabulação como espaço em branco e a interpreta corretamente.

O payload é assim:

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

Após a verificação da palavra-chave, uma lista de bloqueio de tipos impede classes java.*. No entanto, as classes do Spring não estavam nessa lista. Como resultado, a lista incompleta, combinada com um filtro fraco para new, permitiu o carregamento de classes como FileSystemResource. Isso fez com que um arquivo fosse gravado no disco. Em teoria, um invasor poderia colocar um arquivo JSP que chama ProcessBuilder e executa um RCE.

Duas defesas falharam de forma independente: um problema com espaços em branco na verificação da palavra-chave e uma lista de bloqueio limitada. O bypass funcionou porque as verificações não definiam de forma completa o que era considerado um separador. A EndorLabs publicou uma análise mais detalhada da exploração, caso você queira saber mais.

Confira o repositório no GitHub para ver exemplos funcionais de código seguro e inseguro.

O que você precisa fazer

Aplique a correção primeiro. Atualize para o Thymeleaf 3.1.4, mesmo que você ache que seu código não foi afetado. Não espere os resultados da auditoria.

Se você usa o Thymeleaf por meio do Spring Boot, basta atualizar o parent do starter do Spring Boot para a versão mais recente (atualmente, 3.5.14 ou 4.0.6). Se estiver algumas versões atrás, vale conferir as receitas do OpenRewrite para migrar para a versão mais recente do Spring Boot 3.5 ou do Spring Boot 4.0.

Depois de atualizar, examine seu código para descobrir se strings de template ou a resolução de páginas são geradas dinamicamente a partir de entradas do usuário e passadas diretamente ao mecanismo de templates. Se isso acontece, é um padrão de uso indevido. Corrija o código, não apenas a versão da biblioteca.

A pontuação CVSS 9.1 é real, mas depende de uma condição

Uma pontuação CVSS crítica pressupõe que o pré-requisito foi atendido. Se seu código envia entradas do usuário ao mecanismo de expressões do Thymeleaf, a pontuação 9.1 é adequada, e o impacto é grave. Se não faz isso, a CVE em si não afeta você. Ainda assim, aplique a correção!

A pergunta que sua equipe deve fazer na auditoria não é apenas "qual versão do Thymeleaf estamos usando?". É: "construímos nomes de views ou expressões de template dinamicamente a partir de dados das requisições?"

Atualize o Thymeleaf para a versão 3.1.4 ou superior e, em seguida, descubra a resposta para essa segunda pergunta. Independentemente da resposta, continue analisando suas dependências durante o desenvolvimento e monitorando-as em produção com o Snyk Open Source. E o melhor: você pode começar gratuitamente.

Comece a proteger seus aplicativos Python

Encontre e corrija vulnerabilidades em Python gratuitamente com o Snyk.

Não é necessário informar cartão de crédito.

Ou cadastre-se com Azure AD Docker ID Bitbucket

Ao usar o Snyk, você concorda em cumprir nossas políticas, incluindo os Termos de Serviço e a Política de Privacidade.

Leia mais

Blog

Modelos de ponta encontraram as vulnerabilidades. Só o atacante encontrou as cadeias.

A análise estática encontrou as falhas, mas só os testes de ataque em aplicações ativas provaram como elas poderiam ser encadeadas para causar invasões. Uma comparação entre Evo COS, Claude Security e Claude Code Security.

feature insights context
Blog

Os ataques autônomos já chegaram. A defesa precisa acompanhar o ritmo.

Os atacantes autônomos estão reduzindo o tempo disponível para a defesa. Saiba como a descoberta, a correção, a validação e a prevenção contínuas ajudam as equipes de segurança a acompanhar esse ritmo.

Blog

Por que agentes de programação com IA continuam criando falhas de controle de acesso

Agentes de programação com IA podem gerar uma lógica de autorização que compila e passa pela revisão, mas permite que um tenant acesse os dados de outro. Saiba por que é difícil detectar falhas de controle de acesso e como evitá-las.