SSTI Lab: Read a Secret Through an Email Preview Template

✨ AI Summary
MarketingHub's email preview lets you drop in placeholders like {{name}} and {{company}}. It looks like simple variable substitution — but the engine actually evaluates whatever expression you put between the braces, not just a variable name. That gap is Server-Side Template Injection.
Lab at a glance: Advanced · 110 XP · about 20 minutes · runs in your browser, no signup or setup. Try it yourself first; the full solution is behind a spoiler below.

What this lab teaches

Server-Side Template Injection happens when user input is evaluated as a template expression instead of inserted as plain data. A preview that promises 'just put your name here' becomes dangerous the moment the engine runs arbitrary expressions, because those expressions can reach server-side objects and values.

The lesson: letting users supply the template — not just the data — hands them an expression evaluator running on your server.

How MarketingHub renders your preview

MarketingHub feeds your preview text through the template engine. Instead of restricting the braces to a fixed set of variable names, it evaluates any expression inside them. So an expression that references the engine's configuration object is evaluated and its value is rendered back into the preview — including the secret config flag.

The attack approach

  • Confirm the braces evaluate expressions, not just variable names, by putting a simple calculation inside them.
  • See the calculation resolve in the rendered preview — proof of evaluation.
  • Reference the configuration object the lab exposes through a template expression.
  • Read the secret config value from the rendered output.

Full walkthrough (spoiler)

If a calculation renders but the config is not showing, adjust the expression — open the steps.

Show the step-by-step solution
  1. Put a trivial arithmetic expression between the braces in the preview and render it; the computed result confirms expressions are evaluated.
  2. Replace it with an expression that reads config.flag through the template context.
  3. Render the preview. The engine evaluates the expression and prints the config secret into the output.
  4. Read the flag from the rendered preview. The lab detects the access and marks you solved.

Why it works

The engine treats the braces as an expression to evaluate rather than a key to look up. Once arbitrary expressions run, the template context — including configuration and other objects — is reachable. The preview was meant to substitute a name; instead it executes whatever you write.

Core principleNever let users supply the template. Render a fixed template and pass user values as data, and keep user-facing templating logic-less.

Where this happens in the real world

SSTI in 'customisable' features — email templates, invoices, report builders — is a frequent high-severity finding, and in engines like Jinja2, Twig or ERB it can escalate from reading values to remote code execution. It maps to Injection (A03) in the OWASP Top 10 (2021).

How to defend against it

  • Separate template from data. Users supply values that fill a fixed, developer-controlled template — never the template itself.
  • Use a logic-less template language for anything user-facing so expressions cannot be evaluated.
  • Restrict placeholders to an allowlist of known variable names if users must customise.
  • Run the renderer with least privilege and keep template engines patched.
Mr Elite tip: Any 'customise your template' feature is a prime SSTI candidate. Drop a simple arithmetic expression into the field; if it is computed rather than printed verbatim, the engine is evaluating your input.

Try it, then go further

Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.

❓ Frequently asked questions

What is SSTI?
Server-Side Template Injection — when user input is evaluated as part of a server-side template, letting an attacker run template expressions that read server data and sometimes execute code.
How is SSTI different from XSS?
XSS runs in the victim's browser; SSTI runs on the server inside the template engine. SSTI is often more severe because it can reach server-side objects and escalate to code execution.
Why are 'custom template' features risky?
Because they let users supply the template, not just data — handing them an expression evaluator that runs on your server.
How do I prevent SSTI?
Keep the template developer-controlled and pass user input only as data, use logic-less templating for user-facing content, and allowlist placeholder names.
⚡
Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *