Skip to content

Commit

Permalink
- A Template is explicitly disallowed
Browse files Browse the repository at this point in the history
  from having a url that normalizes to relative outside
  of the root.   That is, if the Lookup is based
  at /home/mytemplates, an include that would place
  the ultimate template at
  /home/mytemplates/../some_other_directory,
  i.e. outside of /home/mytemplates,
  is disallowed.   This usage was never intended
  despite the lack of an explicit check.
  The main issue this causes
  is that module files can be written outside
  of the module root (or raise an error, if file perms aren't
  set up), and can also lead to the same template being
  cached in the lookup under multiple, relative roots.
  TemplateLookup instead has always supported multiple
  file roots for this purpose.
  [ticket:174]
  • Loading branch information
zzzeek committed Sep 28, 2011
1 parent 0e42388 commit 5cd508f
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 13 deletions.
19 changes: 19 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
0.5
- A Template is explicitly disallowed
from having a url that normalizes to relative outside
of the root. That is, if the Lookup is based
at /home/mytemplates, an include that would place
the ultimate template at
/home/mytemplates/../some_other_directory,
i.e. outside of /home/mytemplates,
is disallowed. This usage was never intended
despite the lack of an explicit check.
The main issue this causes
is that module files can be written outside
of the module root (or raise an error, if file perms aren't
set up), and can also lead to the same template being
cached in the lookup under multiple, relative roots.
TemplateLookup instead has always supported multiple
file roots for this purpose.
[ticket:174]

0.4.2
- Fixed bug regarding <%call>/def calls w/ content
whereby the identity of the "caller" callable
Expand Down
2 changes: 1 addition & 1 deletion mako/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php


__version__ = '0.4.2'
__version__ = '0.5.0'

2 changes: 1 addition & 1 deletion mako/lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def get_template(self, uri):
Note the "relativeto" argument is not supported here at the moment.
"""

try:
if self.filesystem_checks:
return self._check(uri, self._collection[uri])
Expand Down
18 changes: 12 additions & 6 deletions mako/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,17 @@ def __init__(self,
else:
self.module_id = "memory:" + hex(id(self))
self.uri = self.module_id


u_norm = self.uri
if u_norm.startswith("/"):
u_norm = u_norm[1:]
u_norm = os.path.normpath(u_norm)
if u_norm.startswith(".."):
raise exceptions.TemplateLookupException(
"Template uri \"%s\" is invalid - "
"it cannot be relative outside "
"of the root path." % self.uri)

self.input_encoding = input_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
Expand Down Expand Up @@ -203,18 +213,14 @@ def __init__(self,
if module_filename is not None:
path = module_filename
elif module_directory is not None:
u = self.uri
if u[0] == '/':
u = u[1:]
path = os.path.abspath(
os.path.join(
os.path.normpath(module_directory),
os.path.normpath(u) + ".py"
u_norm + ".py"
)
)
else:
path = None

module = self._compile_from_file(path, filename)
else:
raise exceptions.RuntimeException(
Expand Down
Empty file.
32 changes: 30 additions & 2 deletions test/test_lookup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from mako.template import Template
from mako import lookup, exceptions
from mako import lookup, exceptions, runtime
from mako.util import FastEncodingBuffer
from util import flatten_result, result_lines
import unittest
import os

from test import TemplateTest, template_base, module_base
from test import TemplateTest, template_base, module_base, assert_raises_message

tl = lookup.TemplateLookup(directories=[template_base])
class LookupTest(unittest.TestCase):
Expand Down Expand Up @@ -74,3 +76,29 @@ def test_check_not_found(self):
)
assert f.uri not in tl._collection

def test_dont_accept_relative_outside_of_root(self):
"""test the mechanics of an include where
the include goes outside of the path"""
tl = lookup.TemplateLookup(directories=[os.path.join(template_base, "subdir")])
index = tl.get_template("index.html")

ctx = runtime.Context(FastEncodingBuffer())
ctx._with_template=index

assert_raises_message(
exceptions.TemplateLookupException,
"Template uri \"../index.html\" is invalid - it "
"cannot be relative outside of the root path",
runtime._lookup_template, ctx, "../index.html", index.uri
)

assert_raises_message(
exceptions.TemplateLookupException,
"Template uri \"../othersubdir/foo.html\" is invalid - it "
"cannot be relative outside of the root path",
runtime._lookup_template, ctx, "../othersubdir/foo.html", index.uri
)

# this is OK since the .. cancels out
t = runtime._lookup_template(ctx, "foo/../index.html", index.uri)

23 changes: 20 additions & 3 deletions test/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from util import flatten_result, result_lines
import codecs
from test import TemplateTest, eq_, template_base, module_base, \
skip_if, assert_raises
skip_if, assert_raises, assert_raises_message

class EncodingTest(TemplateTest):
def test_unicode(self):
Expand Down Expand Up @@ -918,8 +918,25 @@ def _compile_from_file(self, path, filename):
finally:
os.path = current_path



def test_dont_accept_relative_outside_of_root(self):
assert_raises_message(
exceptions.TemplateLookupException,
"Template uri \"../../foo.html\" is invalid - it "
"cannot be relative outside of the root path",
Template, "test", uri="../../foo.html",
)

assert_raises_message(
exceptions.TemplateLookupException,
"Template uri \"/../../foo.html\" is invalid - it "
"cannot be relative outside of the root path",
Template, "test", uri="/../../foo.html",
)

# normalizes in the root is OK
t = Template("test", uri="foo/bar/../../foo.html")
eq_(t.uri, "foo/bar/../../foo.html")

class ModuleTemplateTest(TemplateTest):
def test_module_roundtrip(self):
lookup = TemplateLookup()
Expand Down

0 comments on commit 5cd508f

Please sign in to comment.