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}.
This commit is contained in:
David Ormsbee
2019-08-06 13:29:13 -04:00
parent b77793da5f
commit 483e654fcf

View File

@@ -2,9 +2,9 @@
Template module Template module
""" """
from __future__ import absolute_import from __future__ import absolute_import
from string import Template
from lxml import etree from lxml import etree
from mako.template import Template
from xmodule.raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT, XModule from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT, XModule
@@ -14,8 +14,9 @@ class CustomTagModule(XModule):
This module supports tags of the form This module supports tags of the form
<customtag option="val" option2="val2" impl="tagname"/> <customtag option="val" option2="val2" impl="tagname"/>
In this case, $tagname should refer to a file in data/custom_tags, which contains In this case, $tagname should refer to a file in data/custom_tags, which
a mako template that uses ${option} and ${option2} for the content. contains a Python string.Template formatted template that uses ${option} and
${option2} for the content.
For instance: For instance:
@@ -64,7 +65,7 @@ class CustomTagDescriptor(RawDescriptor):
template_module = system.load_item(template_loc) template_module = system.load_item(template_loc)
template_module_data = template_module.data template_module_data = template_module.data
template = Template(template_module_data) template = Template(template_module_data)
return template.render(**params) return template.safe_substitute(params)
@property @property
def rendered_html(self): def rendered_html(self):