
Template Injection
In a template injection, an attacker smuggles their own computational instructions into a text template of a website. The server mistakes them for a normal part of the template, executes them, and thereby leaks data or surrenders control over the machine.
Many websites are not written letter by letter by hand. Instead, there are text templates with gaps, such as “Hello {}, you have {} new messages”. The server fills these gaps with real values shortly before sending. Such templates are called templates, and the program that fills the gaps is the template engine. A template injection occurs when a user manages to smuggle not just a value but a gap of this kind itself into the template. The engine does not distinguish between the developer’s template and the smuggled-in text – it evaluates both.
Why a computation symbol in the name field is dangerous
Template engines are more than gap-fillers. They can calculate, check conditions, iterate over lists, and access objects of the program. Whoever gets instructions into the template thereby gains access to these capabilities. The classic test is harmless and revealing: you enter {} into an input field. If the number 49 appears on the page, the server has performed the calculation – and the gap is thus proven.
From there, the path is often short. In many engines, nested objects can be used to access system functions, such as operating system commands. The result is called Remote Code Execution: foreign program code runs on the operator’s server. This makes databases, passwords, and customer data reachable. Template injection is therefore considered one of the most severe vulnerabilities in web applications.
It is important to distinguish this from Cross-Site Scripting, or XSS for short. There, smuggled-in code is executed in the visitor’s browser, i.e. on their device. In Server-Side Template Injection, it runs on the server itself. The damage thus does not affect a single user but the entire application.
How the confusion between template and content arises
The mistake almost always lies in the same place. A developer does not insert user input into the gap of a template, but into the template itself. Instead of filling the template “Hello {}” with the value, they insert the entered name directly into the template text and only then let the engine process the result. If the name contains curly braces, they are read as an instruction.
A comparison makes this clear. A form letter has pre-printed sentences and fields to fill in. Normally, you only write in the fields. With a template injection, the sender is also allowed to change the pre-printed part – for example, adding the sentence “Please enclose the original”. Whoever processes the letter later follows this just as they would the genuine text.
Protection therefore does not consist of filters for suspicious characters. Filters can almost always be bypassed. The correct approach is to store templates exclusively as fixed files and to pass user input only as values. In addition, a sandbox helps – that is, an environment in which the engine may only use a few, clearly permitted functions.
From invoice templates to prompt templates
Affected are primarily applications in which users are allowed to design texts themselves. Typical examples are newsletter tools, shop systems with customizable invoices, wikis, and website builders. There, the free editing of templates is a feature, and it is precisely this feature that must be strictly fenced in. Well-known engines such as Jinja2, Twig, Freemarker, or Handlebars therefore regularly appear in security advisories.
In the news, one usually reads about template injection in connection with a CVE number, i.e. an officially registered security issue. Such reports frequently concern widely used standard software. For companies, this means: update promptly, because after publication, attackers automatically search for unpatched servers.
The term is now also used in connection with AI systems. Applications with language models work with prompt templates, i.e. templates for the instruction given to the model. Here too, user text is inserted into a template. The related problem is called Prompt Injection and concerns the instructions given to the model rather than the code on the server. The underlying pattern, however, is the same: data and instructions reside in the same text, and the system cannot tell them apart.