Server-Side Template Injection (SSTI)
User input passed directly into a template engine's render function, allowing attackers to execute arbitrary code on the server by injecting template syntax.
How It Works
Template engines like Handlebars, Nunjucks, Pug, and Jinja2 parse and execute their own syntax. If you pass user input into the template string itself (not just as data), an attacker can inject expressions like `{{7*7}}` or `{{config.SECRET_KEY}}`. In some engines, this leads to full Remote Code Execution.
// BAD: user input in the template string itself
import nunjucks from 'nunjucks';
export async function POST(req: Request) {
const { greeting } = await req.json();
// attacker sends: "Hello {{ process.mainModule.require('child_process').execSync('id') }}"
const html = nunjucks.renderString(`<h1>${greeting}</h1>`, {});
return new Response(html);
}// GOOD: pass user data as template context, not in the template
import nunjucks from 'nunjucks';
export async function POST(req: Request) {
const { greeting } = await req.json();
// User input goes in the data object, never in the template string
const html = nunjucks.renderString('<h1>{{ greeting }}</h1>', { greeting });
return new Response(html);
}Real-World Example
SSTI was the root cause of the Uber hack (2022) via a Jinja2 template injection in an internal tool. PayPal and other major platforms have paid bounties for SSTI vulnerabilities. It consistently leads to full server compromise.
How to Prevent It
- Always pass user data as context variables to templates, never embed it in the template string
- Use sandboxed template rendering (Nunjucks sandbox mode) to restrict what expressions can do
- Validate that user input doesn't contain template syntax characters ({{ }}, {% %})
- Avoid user-defined templates entirely — if needed, use a logic-less engine like Mustache
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
LDAP Injection
highUser input inserted into LDAP search filters without escaping, allowing attackers to manipulate directory queries, bypass authentication, or extract sensitive directory data.
XXE — XML External Entity Injection
highXML parsers configured to process external entity references, allowing attackers to read arbitrary files from the server or trigger SSRF by crafting a malicious XML payload.
HTTP Header Injection (CRLF Injection)
mediumUser-controlled input included in HTTP response headers without sanitization, allowing attackers to inject arbitrary headers or split the response into two separate HTTP responses.
Email Header Injection
mediumUnsanitized user input used in email To, From, CC, or Subject fields, allowing attackers to inject additional recipients and turn your email server into a spam relay.