flawopen.com/SSTI/Freemarker & Velocity

Are Freemarker and Velocity templates safe with user input?

CWE-1336: Server-Side Template InjectionReference page
Short answer

Safe when the user supplies data; unsafe when the user supplies any part of the template. Both engines expose object navigation that reaches Java reflection, and from reflection an attacker reaches Runtime.getRuntime().exec(). Both ship restriction mechanisms; neither should be treated as a robust sandbox for hostile input.

VULNERABLE
// Freemarker — template built from input
String src = "Hello " + userSuppliedName;
Template t = new Template("t", src, cfg);
t.process(model, writer);

// Velocity — evaluating a user string
Velocity.evaluate(context, writer,
                  "log", userTemplate);

// Freemarker's built-ins are the
// classic escalation route, reaching
// object construction and then
// command execution.
FIXED
// Template from a trusted loader;
// user value enters via the model
cfg.setTemplateLoader(
    new ClassTemplateLoader(
        App.class, "/templates"));

Template t = cfg.getTemplate("hello.ftl");
Map<String,Object> model = new HashMap<>();
model.put("name", userSuppliedName);
t.process(model, writer);

// If user templates are unavoidable,
// restrict the object wrapper and run
// the render in an isolated process.

Why Java engines escalate so cleanly

Both engines are designed to let a template call methods on objects placed in the model. Java's reflection API means that from almost any object an attacker can obtain a Class, from a Class obtain a ClassLoader or arbitrary methods, and from there construct and invoke whatever they like. Unlike a scripting language where the dangerous surface is a handful of builtins, in the JVM the entire standard library is reachable once reflection is available.

Freemarker's built-ins — the ?-suffixed operations — have been the repeated route in published research, which is why the engine provides a mechanism to disallow specific unsafe ones.

Hardening, and its limits

Treat every one of these as risk reduction rather than as a boundary. The published history of both engines includes bypasses of their own restriction mechanisms.

FAQ

Is Thymeleaf affected too?

Yes, in the same structural way — Thymeleaf evaluates Spring Expression Language, and SpEL reaches the Java runtime. The commonly reported variant is a controller returning a user-controlled value as the view name, which causes it to be processed as an expression fragment.

We only let administrators edit templates. Is that acceptable?

It is a decision to grant those administrators code execution on the server. That may be acceptable for a small trusted group, but it should be an explicit, documented choice with audit logging — not an incidental consequence of a CMS feature.

Which engine is safest for user-supplied templates?

A logic-less engine such as Mustache, which has no expression language to escalate through. If the requirement is genuinely "users write templates", changing engine is a far stronger control than sandboxing a general-purpose one.

References