← All cybersecurity posts

Server-Side Template Injection (SSTI): Detection and Prevention

Template engines make it easy to build pages and emails from data. When user input becomes part of the template itself, rather than data passed into it, attackers can execute template expressions, which often leads to remote code execution.

The difference between safe and unsafe templating

# Safe: user input is data
render_template_string("Hello {{ name }}", name=user_input)

# Vulnerable: user input is the template
render_template_string("Hello " + user_input)

If user_input is {{7*7}}, the vulnerable version renders Hello 49. That proves the server is evaluating attacker-supplied template code.

Where SSTI appears

  • Customisable emails and notifications: "Edit your welcome email template."
  • Marketing and CMS features that let users write templates.
  • Error pages that render the requested path inside a template.
  • PDF and invoice generation from user-defined layouts.
  • Low-code and workflow tools that evaluate expressions.

From expression to code execution

Each engine differs, but many expose objects that lead to the underlying language runtime. In Jinja2, for example, attackers navigate Python object attributes to reach modules that execute commands. Similar chains exist for Twig, Freemarker, Velocity, Handlebars, ERB and others. Once execution is reached, the impact is the same as any RCE.

Detecting SSTI

Testers submit polyglot payloads containing syntax from multiple engines, such as ${{<%[%'"}}%\, and look for errors or evaluation. Then they narrow down the engine with expressions like {{7*'7'}}, which renders differently across engines. Blind SSTI is detected with time delays or out-of-band callbacks.

How to prevent SSTI

  1. Never concatenate user input into templates. Pass it as variables.
  2. If users must author templates, use a logic-less engine, such as Mustache, or a sandboxed mode, and understand its limits. Sandboxes have been bypassed before.
  3. Restrict available objects and functions in the template context.
  4. Render user templates in an isolated service with no secrets or network access.
  5. Keep template engines updated, as sandbox escapes are patched over time.

Client-side template injection

Frameworks that evaluate expressions in the browser, such as older AngularJS, have a related issue: injected expressions can lead to XSS. Modern frameworks are less susceptible, but avoid rendering untrusted input as template code anywhere.

Testing for SSTI

SecurityInfinity agents test inputs that flow into templates, especially in email, PDF and customisation features, fingerprint the engine and verify evaluation safely. Start free.

Frequently asked questions

Is SSTI the same as XSS?

No. XSS runs in the user's browser. SSTI runs on your server, which usually makes it far more severe.

Are logic-less templates completely safe?

They are much safer, because they do not evaluate arbitrary expressions, but the surrounding code must still avoid treating input as templates.

How common is SSTI?

Less common than XSS or IDOR, but frequently critical when found, especially in products with customisable templates.

Find what attackers can see, before they do.

AI pentesting agents test your web app, API and cloud, and every finding comes with evidence and a fix. First report in about 10 minutes.

Stay ahead of attackers.

New vulnerabilities, breach write-ups and practical fixes. A few emails a month.