Agent Wranglers

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

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.