Mako Template Usage Detected

MEDIUM

Mako templates execute Python expressions without sandboxing. Ensure templates are from trusted sources and user input is not rendered as template code.

Rule Information

Language
Python
Category
Python Core
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythonmakotemplate-injectionsstiserver-side-template-injectionCWE-94OWASP-A03
CWE References

Interactive Playground

Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.

pathfinder scan --ruleset python/PYTHON-LANG-SEC-093 --project .
1
2
3
4
5
6
7
8
9
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

About This Rule

Understanding the vulnerability and how it is detected

Mako is a Python template engine used by web frameworks including Pyramid and TurboGears. Unlike some template engines with sandboxed expression evaluation, Mako templates execute Python expressions in the server's Python environment with no security sandbox.

Server-Side Template Injection (SSTI) occurs when user-supplied content is rendered as part of a template's code section (between <% %> or ${} delimiters) rather than being safely HTML-escaped as data. In Mako, injected template code can access __builtins__, import modules, and execute arbitrary Python.

The primary risks are: (1) using user input as the template string itself (mako.Template(user_input)) and (2) insufficient escaping allowing template syntax characters to reach template evaluation contexts.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

Server-Side Template Injection (SSTI)

If user-controlled content is passed as the template string to mako.Template(), or if user content containing ${} or <% %> is rendered in an expression context, an attacker can inject Python code executed on the server. Payloads like ${__import__("os").system("id")} achieve RCE.

2

Information Disclosure via Template Context

Mako templates have access to all variables in the template rendering context. Injected template code can access and exfiltrate any variable passed to template.render(), including database connections, session objects, configuration dictionaries, and request objects.

3

Sandbox Escape via Python Built-ins

Unlike Jinja2's sandboxed environment, Mako provides no sandbox. Injected Python in a Mako template can directly access __builtins__, __import__(), and any Python object reachable from the template context without restriction.

4

Cross-Site Scripting (XSS) via Insufficient Escaping

Mako's ${variable} expression auto-escapes HTML by default with the h filter, but developers who use ${ variable | n } (raw output) or construct HTML manually can bypass XSS protection, enabling reflected or stored XSS.

How to Fix

Recommended remediation steps

  • 1Never use mako.Template(user_input) or any pattern where user input becomes the template string; load templates from a trusted directory using TemplateLookup.
  • 2Always configure TemplateLookup with a fixed templates directory that only contains developer-controlled template files.
  • 3Enable default_filters=["h"] on TemplateLookup to auto-escape HTML in all ${} expressions by default.
  • 4Avoid the | n (no-escape) filter unless the template variable content has been explicitly validated as safe HTML.
  • 5Pass all user data as template render() arguments, never concatenate user data into template strings.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

This rule detects calls to mako.template.Template() constructor in Python source code. All call sites are flagged to prompt review of whether the template string argument is user-controlled, which would enable SSTI.

Compliance & Standards

Industry frameworks and regulations that require detection of this vulnerability

OWASP Top 10
A03:2021 - Injection (includes SSTI)
CWE Top 25
CWE-94 - Improper Control of Generation of Code
NIST SP 800-53
SI-10: Information Input Validation
PCI DSS v4.0
Requirement 6.2.4 - Protect web-facing applications against injection attacks

References

External resources and documentation

Similar Rules

Explore related security rules for Python

Frequently Asked Questions

Common questions about Mako Template Usage Detected

Mako's ${expression} syntax applies the h (HTML escape) filter by default when output_encoding is set and default_filters includes "h". However, this must be explicitly configured via TemplateLookup. Without this configuration, ${expression} outputs raw unescaped content. Always configure default_filters=["h"] explicitly.
Jinja2 provides a sandboxed execution environment (jinja2.sandbox.SandboxedEnvironment) that restricts access to dangerous built-ins and attributes. Mako has no equivalent sandbox. Both are vulnerable to SSTI if user input is used as the template string, but Mako provides fewer mitigations. Jinja2 is generally preferred for new projects.
Use TemplateLookup to map template names to files in a trusted directory. Accept only a template name (filename) from the user, not a template string. The TemplateLookup directory acts as a chroot-like boundary: lookup.get_template(user_name) is safe if user_name is validated to not contain path traversal sequences (../).
Pyramid uses Mako as one of its template engines via pyramid.mako_templating. When Pyramid loads templates from trusted directories using its registry-based template lookup, the risk is low. The risk is when developers call mako.Template() directly with content derived from user input or untrusted sources.
Look for any code path where a string derived from user input (HTTP parameters, database values, file contents) reaches the mako.Template() constructor or is concatenated into a template string before rendering. Code Pathfinder's taint analysis traces these flows from HTTP input sources to the Template() sink.
h applies HTML entity escaping (< becomes &lt;) and prevents XSS in HTML context. u applies URL encoding for URL parameters. n means no filter (raw output) and should only be used for already-safe HTML content. Always use h as the default filter and explicitly mark content with n only after HTML sanitization (e.g., via bleach).

New feature

Get these findings posted directly on your GitHub pull requests

The Mako Template Usage Detected rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.

See how it works