- Author:
- eternicode
- Posted:
- May 16, 2012
- Language:
- Python
- Version:
- 1.3
- Score:
- 2 (after 2 ratings)
A decorator that restricts the tags and filters available to template loading and parsing within a function.
This is mainly meant to be used when granting users the power of the DTL. You obviously don't want users to be able to do things that could be potentially malicious.
The {% ssi %} tag, for example, could be used to display sensitive data if improperly configured.
{% load %} gives them access to all the unlimited python code you wrote in your templatetags. {% load sudo %}{% sudo rm -rf / %} o_0
Note that the "load" tag (among others) is not listed in the default tag whitelist. If you parse a template (however indirectly) in a function decorated with this, unlisted builtin tags will behave like undefined tags (ie, they will result in a TemplateSyntaxError).
Since {% load %} is not whitelisted, you may want to include some custom tags or filters as "builtins" for convenience. Simply put the module paths to the libraries to include in the extra
kwarg or the extra_libraries
list. Generally, this is not recommended, as these libraries need to be carefully and defensively programmed.
NOTE: This does not do anything about cleaning your rendering context! That's completely up to you! This merely restricts what tags and filters are allowed in the templates.
Examples:
from django.template.loader import get_template
safe_get_template = use_safe_templates(get_template)
tmpl = safe_get_template('myapp/some_template.html')
from django.template import Template
use_safe_templates(Template)('{% load sudo %}')
# TemplateSyntaxError: Invalid block tag 'load'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | from django.utils.functional import wraps
from django import template
# Default tag whitelist
whitelist_tags = [
'comment', 'csrf_token', 'cycle', 'filter', 'firstof', 'for', 'if',
'ifchanged', 'now', 'regroup', 'spaceless', 'templatetag', 'url',
'widthratio', 'with'
]
# Default filter whitelist
whitelist_filters = [
'add', 'addslashes', 'capfirst', 'center', 'cut', 'date', 'default',
'default_if_none', 'dictsort', 'dictsortreversed', 'divisibleby', 'escape',
'escapejs', 'filesizeformat', 'first', 'fix_ampersands', 'floatformat',
'force_escape', 'get_digit', 'iriencode', 'join', 'last', 'length', 'length_is',
'linebreaks', 'linebreaksbr', 'linenumbers', 'ljust', 'lower', 'make_list',
'phone2numeric', 'pluralize', 'pprint', 'random', 'removetags', 'rjust', 'safe',
'safeseq', 'slice', 'slugify', 'stringformat', 'striptags', 'time', 'timesince',
'timeuntil', 'title', 'truncatewords', 'truncatewords_html', 'unordered_list',
'upper', 'urlencode', 'urlize', 'urlizetrunc', 'wordcount', 'wordwrap', 'yesno'
]
# Custom libraries to add to builtins
extra_libraries = [
'myproject.myapp.templatetags.extra_tags',
'myproject.myapp.templatetags.extra_filters',
]
def use_safe_templates(tags=None, filters=None, extra=None):
"""
Cleans the builtin template libraries before running the function (restoring
the builtins afterwards).
Removes any builtin tags and filters that are not enumerated in `tags` and
`filters`, and adds the extra library modules in `extra` to the builtins.
Does not catch any template exceptions (notably, TemplateSyntaxError and
TemplateDoesNotExist may be raised).
"""
def decorate(func):
@wraps(func)
def wrapped(*args, **kwargs):
# Clean out default libraries
# Note: template.builtins is merely a convenience import, we have to work
# with template.base.builtins for this to work right.
template.base.builtins, default_libs = [], template.base.builtins
try:
# Construct new builtin with only whitelisted tags/filters
whitelist = template.Library()
for lib in default_libs:
for tag in lib.tags:
if tag in tags:
whitelist.tags[tag] = lib.tags[tag]
for filter in lib.filters:
if filter in filters:
whitelist.filters[filter] = lib.filters[filter]
# Install whitelist library and extras as builtins
template.base.builtins.append(whitelist)
[template.add_to_builtins(e) for e in extra]
return func(*args, **kwargs)
finally:
# Restore the builtins to their former defaults
template.base.builtins = default_libs
return wrapped
if callable(tags):
# @use_safe_templates
func = tags
tags = whitelist_tags
filters = whitelist_filters
extra = extra_libraries
return decorate(func)
else:
# @use_safe_templates(...)
tags = tags or whitelist_tags
filters = filters or whitelist_filters
extra = extra or extra_libraries
return decorate
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.