From 483e654fcf6bd2cfd2730bac6f0efbad76216eaa Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 6 Aug 2019 13:29:13 -0400 Subject: [PATCH] Make CustomTagModule safe (remove Mako) [SEC-609] Prior to this commit, it was possible for course authoring teams to import and execute Mako templates using the obscure "customtag" tag (CustomTagModule). Since Mako templates can run Python code (e.g. imports, database queries, etc.), this would give a course team the ability to execute arbitrary, unsandboxed code on the server. This commit converts CustomTagModule to use the Python library's string.Template instead. This should be broadly compatible with the most basic and common usage of customtag, which is simple variable substitution in the style of ${var_name}. --- common/lib/xmodule/xmodule/template_module.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py index 04bee9b9c0..0e53562f4a 100644 --- a/common/lib/xmodule/xmodule/template_module.py +++ b/common/lib/xmodule/xmodule/template_module.py @@ -2,9 +2,9 @@ Template module """ from __future__ import absolute_import +from string import Template from lxml import etree -from mako.template import Template from xmodule.raw_module import RawDescriptor from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT, XModule @@ -14,8 +14,9 @@ class CustomTagModule(XModule): This module supports tags of the form - In this case, $tagname should refer to a file in data/custom_tags, which contains - a mako template that uses ${option} and ${option2} for the content. + In this case, $tagname should refer to a file in data/custom_tags, which + contains a Python string.Template formatted template that uses ${option} and + ${option2} for the content. For instance: @@ -64,7 +65,7 @@ class CustomTagDescriptor(RawDescriptor): template_module = system.load_item(template_loc) template_module_data = template_module.data template = Template(template_module_data) - return template.render(**params) + return template.safe_substitute(params) @property def rendered_html(self):