diff --git a/django/conf/__init__.py b/django/conf/__init__.py index ee9a1ee1c5..c0e44e24b2 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -99,7 +99,6 @@ class Settings(BaseSettings): mod = importlib.import_module(self.SETTINGS_MODULE) tuple_settings = ( - "ALLOWED_INCLUDE_ROOTS", "INSTALLED_APPS", "TEMPLATE_DIRS", "LOCALE_PATHS", diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 6b759d8454..a6e3acf341 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -260,10 +260,6 @@ DISALLOWED_USER_AGENTS = [] ABSOLUTE_URL_OVERRIDES = {} -# List of strings representing allowed prefixes for the {% ssi %} tag. -# Example: ['/home/html', '/var/www'] -ALLOWED_INCLUDE_ROOTS = [] - # List of compiled regular expression objects representing URLs that need not # be reported by BrokenLinkEmailsMiddleware. Here are a few examples: # import re diff --git a/django/core/checks/compatibility/django_1_8_0.py b/django/core/checks/compatibility/django_1_8_0.py index c0d8d0a779..ea82bf7c11 100644 --- a/django/core/checks/compatibility/django_1_8_0.py +++ b/django/core/checks/compatibility/django_1_8_0.py @@ -10,7 +10,6 @@ def check_duplicate_template_settings(app_configs, **kwargs): if settings.TEMPLATES: values = [ 'TEMPLATE_DIRS', - 'ALLOWED_INCLUDE_ROOTS', 'TEMPLATE_CONTEXT_PROCESSORS', 'TEMPLATE_DEBUG', 'TEMPLATE_LOADERS', diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 9a86279d38..ec1b486b24 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -1,7 +1,6 @@ """Default tags used by the template system, available to all templates.""" from __future__ import unicode_literals -import os import re import sys import warnings @@ -19,7 +18,7 @@ from django.utils.safestring import mark_safe from .base import ( BLOCK_TAG_END, BLOCK_TAG_START, COMMENT_TAG_END, COMMENT_TAG_START, SINGLE_BRACE_END, SINGLE_BRACE_START, VARIABLE_ATTRIBUTE_SEPARATOR, - VARIABLE_TAG_END, VARIABLE_TAG_START, Context, Node, NodeList, Template, + VARIABLE_TAG_END, VARIABLE_TAG_START, Context, Node, NodeList, TemplateSyntaxError, VariableDoesNotExist, kwarg_re, render_value_in_context, token_kwargs, ) @@ -373,44 +372,6 @@ class RegroupNode(Node): return '' -def include_is_allowed(filepath, allowed_include_roots): - filepath = os.path.abspath(filepath) - for root in allowed_include_roots: - if filepath.startswith(root): - return True - return False - - -class SsiNode(Node): - def __init__(self, filepath, parsed): - self.filepath = filepath - self.parsed = parsed - - def render(self, context): - filepath = self.filepath.resolve(context) - - if not include_is_allowed(filepath, context.template.engine.allowed_include_roots): - if settings.DEBUG: - return "[Didn't have permission to include file]" - else: - return '' # Fail silently for invalid includes. - try: - with open(filepath, 'r') as fp: - output = fp.read() - except IOError: - output = '' - if self.parsed: - try: - t = Template(output, name=filepath, engine=context.template.engine) - return t.render(context) - except TemplateSyntaxError as e: - if settings.DEBUG: - return "[Included template had syntax error: %s]" % e - else: - return '' # Fail silently for invalid included templates. - return output - - class LoadNode(Node): def render(self, context): return '' @@ -1091,42 +1052,6 @@ def ifchanged(parser, token): return IfChangedNode(nodelist_true, nodelist_false, *values) -@register.tag -def ssi(parser, token): - """ - Outputs the contents of a given file into the page. - - Like a simple "include" tag, the ``ssi`` tag includes the contents - of another file -- which must be specified using an absolute path -- - in the current page:: - - {% ssi "/home/html/ljworld.com/includes/right_generic.html" %} - - If the optional "parsed" parameter is given, the contents of the included - file are evaluated as template code, with the current context:: - - {% ssi "/home/html/ljworld.com/includes/right_generic.html" parsed %} - """ - warnings.warn( - "The {% ssi %} tag is deprecated. Use the {% include %} tag instead.", - RemovedInDjango110Warning, - ) - - bits = token.split_contents() - parsed = False - if len(bits) not in (2, 3): - raise TemplateSyntaxError("'ssi' tag takes one argument: the path to" - " the file to be included") - if len(bits) == 3: - if bits[2] == 'parsed': - parsed = True - else: - raise TemplateSyntaxError("Second (optional) argument to %s tag" - " must be 'parsed'" % bits[0]) - filepath = parser.compile_filter(bits[1]) - return SsiNode(filepath, parsed) - - def find_library(parser, name): try: return parser.libraries[name] diff --git a/django/template/engine.py b/django/template/engine.py index 2c9e2c2892..75d39c82a0 100644 --- a/django/template/engine.py +++ b/django/template/engine.py @@ -23,14 +23,11 @@ class Engine(object): 'django.template.loader_tags', ] - def __init__(self, dirs=None, app_dirs=False, - allowed_include_roots=None, context_processors=None, + def __init__(self, dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None): if dirs is None: dirs = [] - if allowed_include_roots is None: - allowed_include_roots = [] if context_processors is None: context_processors = [] if loaders is None: @@ -46,13 +43,8 @@ class Engine(object): if builtins is None: builtins = [] - if isinstance(allowed_include_roots, six.string_types): - raise ImproperlyConfigured( - "allowed_include_roots must be a tuple, not a string.") - self.dirs = dirs self.app_dirs = app_dirs - self.allowed_include_roots = allowed_include_roots self.context_processors = context_processors self.debug = debug self.loaders = loaders diff --git a/django/template/utils.py b/django/template/utils.py index cbf0de148d..d809a47f58 100644 --- a/django/template/utils.py +++ b/django/template/utils.py @@ -40,7 +40,6 @@ class EngineHandler(object): 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': settings.TEMPLATE_DIRS, 'OPTIONS': { - 'allowed_include_roots': settings.ALLOWED_INCLUDE_ROOTS, 'context_processors': settings.TEMPLATE_CONTEXT_PROCESSORS, 'debug': settings.TEMPLATE_DEBUG, 'loaders': settings.TEMPLATE_LOADERS, diff --git a/django/test/signals.py b/django/test/signals.py index f7836637e8..9f7958d83b 100644 --- a/django/test/signals.py +++ b/django/test/signals.py @@ -85,7 +85,6 @@ def reset_template_engines(**kwargs): if kwargs['setting'] in { 'TEMPLATES', 'TEMPLATE_DIRS', - 'ALLOWED_INCLUDE_ROOTS', 'TEMPLATE_CONTEXT_PROCESSORS', 'TEMPLATE_DEBUG', 'TEMPLATE_LOADERS', diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 8b9ab3254c..10bced6dea 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -691,10 +691,10 @@ details on these changes. handling. (This is faster than the usual deprecation path; see the :doc:`Django 1.4 release notes`.) -* The :ttag:`url` and :ttag:`ssi` template tags will be - modified so that the first argument to each tag is a template variable, not - an implied string. In 1.4, this behavior is provided by a version of the tag - in the ``future`` template tag library. +* The ``url`` and ``ssi`` template tags will be modified so that the first + argument to each tag is a template variable, not an implied string. In 1.4, + this behavior is provided by a version of the tag in the ``future`` template + tag library. * The ``reset`` and ``sqlreset`` management commands will be removed. diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 208e3fb81f..36f0b6222b 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -252,9 +252,9 @@ that might occur as a result of a version upgrade. * **1_8.W001**: The standalone ``TEMPLATE_*`` settings were deprecated in Django 1.8 and the :setting:`TEMPLATES` dictionary takes precedence. You must put the values of the following settings into your defaults ``TEMPLATES`` - dict: :setting:`TEMPLATE_DIRS`, :setting:`ALLOWED_INCLUDE_ROOTS`, - :setting:`TEMPLATE_CONTEXT_PROCESSORS`, :setting:`TEMPLATE_DEBUG`, - :setting:`TEMPLATE_LOADERS`, :setting:`TEMPLATE_STRING_IF_INVALID`. + dict: :setting:`TEMPLATE_DIRS`, :setting:`TEMPLATE_CONTEXT_PROCESSORS`, + :setting:`TEMPLATE_DEBUG`, :setting:`TEMPLATE_LOADERS`, + :setting:`TEMPLATE_STRING_IF_INVALID`. Admin ----- diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 6a398e1c60..a5d8715e69 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -99,32 +99,6 @@ This validation only applies via :meth:`~django.http.HttpRequest.get_host()`; if your code accesses the ``Host`` header directly from ``request.META`` you are bypassing this security protection. -.. setting:: ALLOWED_INCLUDE_ROOTS - -ALLOWED_INCLUDE_ROOTS ---------------------- - -Default: ``[]`` (Empty list) - -.. deprecated:: 1.8 - - This setting, along with the :ttag:`ssi` template tag, is deprecated and - will be removed in Django 1.10. - -.. versionchanged:: 1.8 - - You can also set the ``'allowed_include_roots'`` option in the - :setting:`OPTIONS ` of a ``DjangoTemplates`` backend - instead. - -A list of strings representing allowed prefixes for the ``{% ssi %}`` template -tag. This is a security measure, so that template authors can't access files -that they shouldn't be accessing. - -For example, if :setting:`ALLOWED_INCLUDE_ROOTS` is ``['/home/html', '/var/www']``, -then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}`` -wouldn't. - .. setting:: APPEND_SLASH APPEND_SLASH @@ -3433,7 +3407,6 @@ Serialization Templates --------- -* :setting:`ALLOWED_INCLUDE_ROOTS` * :setting:`TEMPLATES` * :setting:`TEMPLATE_CONTEXT_PROCESSORS` * :setting:`TEMPLATE_DEBUG` diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt index a8311d30fd..5f6e12934c 100644 --- a/docs/ref/templates/api.txt +++ b/docs/ref/templates/api.txt @@ -48,7 +48,7 @@ probably isn't the documentation you're looking for. An instance of the of that backend and any attribute defaults mentioned below are overridden by what's passed by :class:`~django.template.backends.django.DjangoTemplates`. -.. class:: Engine(dirs=None, app_dirs=False, allowed_include_roots=None, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None) +.. class:: Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None) .. versionadded:: 1.8 @@ -65,21 +65,6 @@ what's passed by :class:`~django.template.backends.django.DjangoTemplates`. It defaults to ``False``. - * ``allowed_include_roots`` is a list of strings representing allowed - prefixes for the ``{% ssi %}`` template tag. This is a security measure, - so that template authors can't access files that they shouldn't be - accessing. - - For example, if ``'allowed_include_roots'`` is ``['/home/html', - '/var/www']``, then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% - ssi /etc/passwd %}`` wouldn't. - - It defaults to an empty list. - - .. deprecated:: 1.8 - - ``allowed_include_roots`` is deprecated. - * ``context_processors`` is a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt index 359907d261..1da27a18e6 100644 --- a/docs/ref/templates/builtins.txt +++ b/docs/ref/templates/builtins.txt @@ -958,45 +958,6 @@ this example, the space around ``Hello`` won't be stripped:: {% endspaceless %} -.. templatetag:: ssi - -ssi -^^^ - -.. deprecated:: 1.8 - - This tag has been deprecated and will be removed in Django 1.10. Use the - :ttag:`include` tag instead. - -Outputs the contents of a given file into the page. - -Like a simple :ttag:`include` tag, ``{% ssi %}`` includes the contents of -another file -- which must be specified using an absolute path -- in the -current page:: - - {% ssi '/home/html/ljworld.com/includes/right_generic.html' %} - -The first parameter of ``ssi`` can be a quoted literal or any other context -variable. - -If the optional ``parsed`` parameter is given, the contents of the included -file are evaluated as template code, within the current context:: - - {% ssi '/home/html/ljworld.com/includes/right_generic.html' parsed %} - -Note that if you use ``{% ssi %}``, you'll need to define -``'allowed_include_roots'`` in the :setting:`OPTIONS ` of -your template engine, as a security measure. - -.. note:: - With the :ttag:`ssi` tag and the ``parsed`` parameter - there is no shared state between files -- each include is a completely - independent rendering process. This means it's not possible for example to - define blocks or alter the context in the current page using the included - file. - -See also: :ttag:`{% include %}`. - .. templatetag:: templatetag templatetag diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt index 52790db091..6706a58de2 100644 --- a/docs/releases/1.3.txt +++ b/docs/releases/1.3.txt @@ -730,8 +730,8 @@ and Ctrl-C test termination) have been made redundant. In view of this redundancy, ``DjangoTestRunner`` has been turned into an empty placeholder class, and will be removed entirely in Django 1.5. -Changes to :ttag:`url` and :ttag:`ssi` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Changes to ``url`` and ``ssi`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Most template tags will allow you to pass in either constants or variables as arguments -- for example:: @@ -745,15 +745,14 @@ context variable ``templ`` that contains the value ``base.html``:: is also legal. -However, due to an accident of history, the :ttag:`url` and -:ttag:`ssi` are different. These tags use the second, quoteless -syntax, but interpret the argument as a constant. This means it isn't -possible to use a context variable as the target of a :ttag:`url` and -:ttag:`ssi` tag. +However, due to an accident of history, the ``url`` and ``ssi`` are different. +These tags use the second, quoteless syntax, but interpret the argument as a +constant. This means it isn't possible to use a context variable as the target +of a ``url`` and ``ssi`` tag. Django 1.3 marks the start of the process to correct this historical accident. Django 1.3 adds a new template library -- ``future`` -- that -provides alternate implementations of the :ttag:`url` and :ttag:`ssi` +provides alternate implementations of the ``url`` and ``ssi`` template tags. This ``future`` library implement behavior that makes the handling of the first argument consistent with the handling of all other variables. So, an existing template that contains:: diff --git a/docs/releases/1.4.7.txt b/docs/releases/1.4.7.txt index 64d308894c..c50d938bc4 100644 --- a/docs/releases/1.4.7.txt +++ b/docs/releases/1.4.7.txt @@ -7,11 +7,11 @@ Django 1.4.7 release notes Django 1.4.7 fixes one security issue present in previous Django releases in the 1.4 series. -Directory traversal vulnerability in :ttag:`ssi` template tag -------------------------------------------------------------- +Directory traversal vulnerability in ``ssi`` template tag +--------------------------------------------------------- In previous versions of Django it was possible to bypass the -:setting:`ALLOWED_INCLUDE_ROOTS` setting used for security with the :ttag:`ssi` +``ALLOWED_INCLUDE_ROOTS`` setting used for security with the ``ssi`` template tag by specifying a relative path that starts with one of the allowed roots. For example, if ``ALLOWED_INCLUDE_ROOTS = ("/var/www",)`` the following would be possible: @@ -21,5 +21,5 @@ would be possible: {% ssi "/var/www/../../etc/passwd" %} In practice this is not a very common problem, as it would require the template -author to put the :ttag:`ssi` file in a user-controlled variable, but it's +author to put the ``ssi`` file in a user-controlled variable, but it's possible in principle. diff --git a/docs/releases/1.5.3.txt b/docs/releases/1.5.3.txt index bdf68d5621..3d03eed74a 100644 --- a/docs/releases/1.5.3.txt +++ b/docs/releases/1.5.3.txt @@ -8,11 +8,11 @@ This is Django 1.5.3, the third release in the Django 1.5 series. It addresses one security issue and also contains an opt-in feature to enhance the security of :mod:`django.contrib.sessions`. -Directory traversal vulnerability in :ttag:`ssi` template tag -------------------------------------------------------------- +Directory traversal vulnerability in ``ssi`` template tag +--------------------------------------------------------- In previous versions of Django it was possible to bypass the -:setting:`ALLOWED_INCLUDE_ROOTS` setting used for security with the :ttag:`ssi` +``ALLOWED_INCLUDE_ROOTS`` setting used for security with the ``ssi`` template tag by specifying a relative path that starts with one of the allowed roots. For example, if ``ALLOWED_INCLUDE_ROOTS = ("/var/www",)`` the following would be possible: @@ -22,8 +22,8 @@ would be possible: {% ssi "/var/www/../../etc/passwd" %} In practice this is not a very common problem, as it would require the template -author to put the :ttag:`ssi` file in a user-controlled variable, but it's -possible in principle. +author to put the ``ssi`` file in a user-controlled variable, but it's possible +in principle. Mitigating a remote-code execution vulnerability in :mod:`django.contrib.sessions` ---------------------------------------------------------------------------------- diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index ff6043a332..993215ce34 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -1734,7 +1734,7 @@ Loading ``ssi`` and ``url`` template tags from ``future`` library Django 1.3 introduced ``{% load ssi from future %}`` and ``{% load url from future %}`` syntax for forward compatibility of the -:ttag:`ssi` and :ttag:`url` template tags. This syntax is now deprecated and +``ssi`` and :ttag:`url` template tags. This syntax is now deprecated and will be removed in Django 1.9. You can simply remove the ``{% load ... from future %}`` tags. diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index a2d98656b6..d13abcabfc 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -1654,7 +1654,7 @@ Django 1.10. ``ssi`` template tag ~~~~~~~~~~~~~~~~~~~~ -The :ttag:`ssi` template tag allows files to be included in a template by +The ``ssi`` template tag allows files to be included in a template by absolute path. This is of limited use in most deployment situations, and the :ttag:`include` tag often makes more sense. This tag is now deprecated and will be removed in Django 1.10. diff --git a/docs/topics/templates.txt b/docs/topics/templates.txt index 94ee9904a6..a2ccdb0c9f 100644 --- a/docs/topics/templates.txt +++ b/docs/topics/templates.txt @@ -348,21 +348,6 @@ applications. This generic name was kept for backwards-compatibility. ``DjangoTemplates`` engines accept the following :setting:`OPTIONS `: -* ``'allowed_include_roots'``: a list of strings representing allowed prefixes - for the ``{% ssi %}`` template tag. This is a security measure, so that - template authors can't access files that they shouldn't be accessing. - - For example, if ``'allowed_include_roots'`` is ``['/home/html', - '/var/www']``, then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% - ssi /etc/passwd %}`` wouldn't. - - It defaults to an empty list. - - .. deprecated:: 1.8 - - ``allowed_include_roots`` is deprecated because the {% ssi %} tag is - deprecated. - * ``'context_processors'``: a list of dotted Python paths to callables that are used to populate the context when a template is rendered with a request. These callables take a request object as their argument and return a diff --git a/tests/settings_tests/tests.py b/tests/settings_tests/tests.py index 32b297b427..90b2b8e580 100644 --- a/tests/settings_tests/tests.py +++ b/tests/settings_tests/tests.py @@ -472,7 +472,6 @@ class TestListSettings(unittest.TestCase): ImproperlyConfigured if they are set to a string instead of a list or tuple. """ list_or_tuple_settings = ( - "ALLOWED_INCLUDE_ROOTS", "INSTALLED_APPS", "TEMPLATE_DIRS", "LOCALE_PATHS", diff --git a/tests/template_tests/syntax_tests/test_ssi.py b/tests/template_tests/syntax_tests/test_ssi.py deleted file mode 100644 index 0fd9af7712..0000000000 --- a/tests/template_tests/syntax_tests/test_ssi.py +++ /dev/null @@ -1,112 +0,0 @@ -from __future__ import unicode_literals - -import os - -from django.template import Context, Engine -from django.test import SimpleTestCase, ignore_warnings -from django.utils.deprecation import RemovedInDjango110Warning - -from ..utils import ROOT, setup - - -@ignore_warnings(category=RemovedInDjango110Warning) -class SsiTagTests(SimpleTestCase): - - # Test normal behavior - @setup({'ssi01': '{%% ssi "%s" %%}' % os.path.join( - ROOT, 'templates', 'ssi_include.html', - )}) - def test_ssi01(self): - output = self.engine.render_to_string('ssi01') - self.assertEqual(output, 'This is for testing an ssi include. {{ test }}\n') - - @setup({'ssi02': '{%% ssi "%s" %%}' % os.path.join( - ROOT, 'not_here', - )}) - def test_ssi02(self): - output = self.engine.render_to_string('ssi02') - self.assertEqual(output, ''), - - @setup({'ssi03': "{%% ssi '%s' %%}" % os.path.join( - ROOT, 'not_here', - )}) - def test_ssi03(self): - output = self.engine.render_to_string('ssi03') - self.assertEqual(output, ''), - - # Test passing as a variable - @setup({'ssi04': '{% ssi ssi_file %}'}) - def test_ssi04(self): - output = self.engine.render_to_string('ssi04', { - 'ssi_file': os.path.join(ROOT, 'templates', 'ssi_include.html') - }) - self.assertEqual(output, 'This is for testing an ssi include. {{ test }}\n') - - @setup({'ssi05': '{% ssi ssi_file %}'}) - def test_ssi05(self): - output = self.engine.render_to_string('ssi05', {'ssi_file': 'no_file'}) - self.assertEqual(output, '') - - # Test parsed output - @setup({'ssi06': '{%% ssi "%s" parsed %%}' % os.path.join( - ROOT, 'templates', 'ssi_include.html', - )}) - def test_ssi06(self): - output = self.engine.render_to_string('ssi06', {'test': 'Look ma! It parsed!'}) - self.assertEqual(output, 'This is for testing an ssi include. ' - 'Look ma! It parsed!\n') - - @setup({'ssi07': '{%% ssi "%s" parsed %%}' % os.path.join( - ROOT, 'not_here', - )}) - def test_ssi07(self): - output = self.engine.render_to_string('ssi07', {'test': 'Look ma! It parsed!'}) - self.assertEqual(output, '') - - # Test space in file name - @setup({'ssi08': '{%% ssi "%s" %%}' % os.path.join( - ROOT, 'templates', 'ssi include with spaces.html', - )}) - def test_ssi08(self): - output = self.engine.render_to_string('ssi08') - self.assertEqual(output, 'This is for testing an ssi include ' - 'with spaces in its name. {{ test }}\n') - - @setup({'ssi09': '{%% ssi "%s" parsed %%}' % os.path.join( - ROOT, 'templates', 'ssi include with spaces.html', - )}) - def test_ssi09(self): - output = self.engine.render_to_string('ssi09', {'test': 'Look ma! It parsed!'}) - self.assertEqual(output, 'This is for testing an ssi include ' - 'with spaces in its name. Look ma! It parsed!\n') - - -@ignore_warnings(category=RemovedInDjango110Warning) -class SSISecurityTests(SimpleTestCase): - - def setUp(self): - self.ssi_dir = os.path.join(ROOT, "templates", "first") - self.engine = Engine(allowed_include_roots=(self.ssi_dir,)) - - def render_ssi(self, path): - # the path must exist for the test to be reliable - self.assertTrue(os.path.exists(path)) - return self.engine.from_string('{%% ssi "%s" %%}' % path).render(Context({})) - - def test_allowed_paths(self): - acceptable_path = os.path.join(self.ssi_dir, "..", "first", "test.html") - self.assertEqual(self.render_ssi(acceptable_path), 'First template\n') - - def test_relative_include_exploit(self): - """ - May not bypass allowed_include_roots with relative paths - - e.g. if allowed_include_roots = ("/var/www",), it should not be - possible to do {% ssi "/var/www/../../etc/passwd" %} - """ - disallowed_paths = [ - os.path.join(self.ssi_dir, "..", "ssi_include.html"), - os.path.join(self.ssi_dir, "..", "second", "test.html"), - ] - for disallowed_path in disallowed_paths: - self.assertEqual(self.render_ssi(disallowed_path), '') diff --git a/tests/template_tests/utils.py b/tests/template_tests/utils.py index d78f0eac6c..f8585979d7 100644 --- a/tests/template_tests/utils.py +++ b/tests/template_tests/utils.py @@ -55,7 +55,6 @@ def setup(templates, *args, **kwargs): libraries = getattr(self, 'libraries', {}) self.engine = Engine( - allowed_include_roots=[ROOT], libraries=libraries, loaders=loaders, ) @@ -65,7 +64,6 @@ def setup(templates, *args, **kwargs): func(self) self.engine = Engine( - allowed_include_roots=[ROOT], libraries=libraries, loaders=loaders, string_if_invalid='INVALID', @@ -74,7 +72,6 @@ def setup(templates, *args, **kwargs): func(self) self.engine = Engine( - allowed_include_roots=[ROOT], debug=True, libraries=libraries, loaders=loaders,