Add mako templating plugin and XSS profile

Adds plugin to warn on Mako templates. Since mako does not have template wide
autoescaping (that we can verify is turned on), a developer is responsible to
escape each variable individually in the templates. This is higher than info
because the *only* way to escape is via the variables, but not set to ERROR
because we can't know for sure if any of those variables are used and/or
malicious.

Also add an XSS profile.

Change-Id: I65515f9584d67d8b7b58b71b6ddb447c307675d1
This commit is contained in:
Rob Fletcher 2015-02-24 10:02:52 -08:00
parent 6158918052
commit 27eea75f3c
6 changed files with 54 additions and 1 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ venv*
.DS_Store
*.egg
*.egg-info
.eggs/
.tox
.testrepository
build/*

View File

@ -28,6 +28,11 @@ include:
exclude_dirs:
profiles:
XSS:
include:
- jinja2_autoescape_false
- use_of_mako_templates
ShellInjection:
include:
- subprocess_popen_with_shell_equals_true

View File

@ -21,7 +21,7 @@ from bandit.core.test_properties import *
@checks('Call')
def autoescape_false(context):
def jinja2_autoescape_false(context):
# check type just to be safe
if type(context.call_function_name_qual) == str:
qualname_list = context.call_function_name_qual.split('.')

View File

@ -0,0 +1,33 @@
# -*- coding:utf-8 -*-
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import bandit
from bandit.core.test_properties import *
@checks('Call')
def use_of_mako_templates(context):
# check type just to be safe
if type(context.call_function_name_qual) == str:
qualname_list = context.call_function_name_qual.split('.')
func = qualname_list[-1]
if 'mako' in qualname_list and func == 'Template':
# unlike Jinja2, mako does not have a template wide autoescape
# feature and thus each variable must be carefully sanitized.
return(bandit.WARN, "Mako templates allow HTML/JS rendering"
" by default and are inherently open to XSS attacks."
" Ensure variables in all templates are properly"
" sanitized via the 'n', 'h' or 'x' flags (depending on"
" context). For example, to HTML escape the variable 'data'"
" do ${ data |h }")

View File

@ -0,0 +1,11 @@
from mako.template import Template
import mako
from mako import template
Template("hello")
# XXX(fletcher): for some reason, bandit is missing the one below. keeping it
# in for now so that if it gets fixed inadvertitently we know.
mako.template.Template("hern")
template.Template("hern")

View File

@ -218,3 +218,6 @@ class FunctionalTests(unittest.TestCase):
def test_secret_config_option(self):
'''Test for `secret=True` in Oslo's config.'''
self.check_example('secret-config-option.py', info=1, warn=2)
def test_mako_templating(self):
self.check_example('mako_templating.py', warn=3)