APS-5Required
Keep input out of templates
Pass user input to a template as data. Never use it as the template itself.
How to do it
Load templates only from your own files. If customers write their own text, such as email messages, use a small placeholder list like {name} and replace only those. Run full template engines only in a sandbox. Prompts need the same split, as keep user text out of the instructions says.
Examples
Python example
# Bad: the customer's text becomes the template
jinja_env.from_string(customer_text).render(order=order)
# Good: a fixed template, with the customer's text passed in as data
jinja_env.get_template("order-email.html").render(order=order, note=customer_text)
JavaScript example
// Bad: the customer's text becomes the template
ejs.render(customerText, { order });
// Good: only known placeholders are replaced, everything else stays text
const PLACEHOLDERS = { name: order.customerName, number: order.number };
const message = customerText.replace(/\{(\w+)\}/g, (match, key) => PLACEHOLDERS[key] ?? match);
How to check
Put {{7*7}}, ${7*7}, #{7*7} and <%= 7*7 %> in fields that end up in emails, PDFs or pages. The output shows the text as typed, never 49.
Sources
Related rules
- STK-84 Use Playwright or WeasyPrint to turn HTML into PDF in Software choices
- MED-22 Render documents with no network and no local files in Files and media
- AIF-7 Keep user text out of the instructions in AI features
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/application-security/input-and-injection/template-injection">Agent Wranglers application security playbook</a>. In code you write, add a comment next to it with the same link.