Chapter 2 · Practice 5 of 5
Apply the same rule to templates, eval, LDAP and expression languages
Why it matters
Any component that evaluates a string is an interpreter. OWASP's A05:2025 lists NoSQL, OS command, ORM, LDAP, and Expression Language or OGNL injection alongside SQL. A few that catch application developers:
| Interpreter | Unsafe pattern | Safe pattern |
|---|---|---|
| JavaScript | eval, new Function, vm on input | parse data with JSON.parse, never run it |
| Python | eval, exec on input | ast.literal_eval for literals, or a real parser |
| Server-side templates | rendering a template string the user wrote | user text only as a variable inside a fixed template |
| LDAP | building filters with string formatting | the library's filter escaping functions |
| Regex | new RegExp(userInput) | escape the input, or match with plain string methods |
Server-side template injection is the one that surprises people. Rendering render_template_string(user_bio) in Jinja2 lets the bio run template expressions on the server. Templates must come from your code; user text goes in as data.
If you build a feature that genuinely runs user logic (formulas, rules, plugins), use a purpose-built, sandboxed expression language with no access to the host, not your own language's eval.