#1 Version bump
Merged 3 years ago by mikelo2. Opened 3 years ago by mikelo2.
rpms/ mikelo2/bandit master  into  master

@@ -1,210 +0,0 @@ 

- diff --git a/setup.cfg b/setup.cfg

- index 0c0546c..ac21b7e 100644

- --- a/setup.cfg

- +++ b/setup.cfg

- @@ -1,93 +1,113 @@

-  [metadata]

-  name = bandit

-  summary = Security oriented static analyser for python code.

- -description-file = 

- -	README.rst

- +description-file =

- +    README.rst

-  author = OpenStack Security Group

-  author-email = openstack-dev@lists.openstack.org

-  home-page = https://wiki.openstack.org/wiki/Security/Projects/Bandit

- -classifier = 

- -	Environment :: OpenStack

- -	Intended Audience :: Information Technology

- -	Intended Audience :: System Administrators

- -	Intended Audience :: Developers

- -	License :: OSI Approved :: Apache Software License

- -	Operating System :: POSIX :: Linux

- -	Operating System :: MacOS :: MacOS X

- -	Programming Language :: Python

- -	Programming Language :: Python :: 2

- -	Programming Language :: Python :: 2.7

- -	Programming Language :: Python :: 3

- -	Programming Language :: Python :: 3.5

- -	Topic :: Security

- +classifier =

- +    Environment :: OpenStack

- +    Intended Audience :: Information Technology

- +    Intended Audience :: System Administrators

- +    Intended Audience :: Developers

- +    License :: OSI Approved :: Apache Software License

- +    Operating System :: POSIX :: Linux

- +    Operating System :: MacOS :: MacOS X

- +    Programming Language :: Python

- +    Programming Language :: Python :: 2

- +    Programming Language :: Python :: 2.7

- +    Programming Language :: Python :: 3

- +    Programming Language :: Python :: 3.5

- +    Topic :: Security

-  

-  [entry_points]

- -console_scripts = 

- -	bandit = bandit.cli.main:main

- -	bandit-config-generator = bandit.cli.config_generator:main

- -	bandit-baseline = bandit.cli.baseline:main

- -bandit.blacklists = 

- -	calls = bandit.blacklists.calls:gen_blacklist

- -	imports = bandit.blacklists.imports:gen_blacklist

- -bandit.formatters = 

- -	csv = bandit.formatters.csv:report

- -	json = bandit.formatters.json:report

- -	txt = bandit.formatters.text:report

- -	xml = bandit.formatters.xml:report

- -	html = bandit.formatters.html:report

- -	screen = bandit.formatters.screen:report

- -bandit.plugins = 

- -	# bandit/plugins/app_debug.py

- -	flask_debug_true = bandit.plugins.app_debug:flask_debug_true

- -	# bandit/plugins/asserts.py

- -	assert_used = bandit.plugins.asserts:assert_used

- -	# bandit/plugins/crypto_request_no_cert_validation.py

- -	request_with_no_cert_validation = bandit.plugins.crypto_request_no_cert_validation:request_with_no_cert_validation

- -	# bandit/plugins/exec_as_root.py

- -	execute_with_run_as_root_equals_true = bandit.plugins.exec_as_root:execute_with_run_as_root_equals_true

- -	# bandit/plugins/exec.py

- -	exec_used = bandit.plugins.exec:exec_used

- -	# bandit/plugins/general_bad_File_permissions.py

- -	set_bad_file_permissions = bandit.plugins.general_bad_file_permissions:set_bad_file_permissions

- -	# bandit/plugins/general_bind_all_interfaces.py

- -	hardcoded_bind_all_interfaces = bandit.plugins.general_bind_all_interfaces:hardcoded_bind_all_interfaces

- -	# bandit/plugins/general_hardcoded_password.py

- -	hardcoded_password_string = bandit.plugins.general_hardcoded_password:hardcoded_password_string

- -	hardcoded_password_funcarg = bandit.plugins.general_hardcoded_password:hardcoded_password_funcarg

- -	hardcoded_password_default = bandit.plugins.general_hardcoded_password:hardcoded_password_default

- -	# bandit/plugins/general_hardcoded_tmp.py

- -	hardcoded_tmp_directory = bandit.plugins.general_hardcoded_tmp:hardcoded_tmp_directory

- -	# bandit/plugins/injection_paramiko.py

- -	paramiko_calls = bandit.plugins.injection_paramiko:paramiko_calls

- -	# bandit/plugins/injection_shell.py

- -	subprocess_popen_with_shell_equals_true = bandit.plugins.injection_shell:subprocess_popen_with_shell_equals_true

- -	subprocess_without_shell_equals_true = bandit.plugins.injection_shell:subprocess_without_shell_equals_true

- -	any_other_function_with_shell_equals_true = bandit.plugins.injection_shell:any_other_function_with_shell_equals_true

- -	start_process_with_a_shell = bandit.plugins.injection_shell:start_process_with_a_shell

- -	start_process_with_no_shell = bandit.plugins.injection_shell:start_process_with_no_shell

- -	start_process_with_partial_path = bandit.plugins.injection_shell:start_process_with_partial_path

- -	# bandit/plugins/injection_sql.py

- -	hardcoded_sql_expressions = bandit.plugins.injection_sql:hardcoded_sql_expressions

- -	# bandit/plugins/injection_wildcard.py

- -	linux_commands_wildcard_injection = bandit.plugins.injection_wildcard:linux_commands_wildcard_injection

- -	# bandit/plugins/insecure_ssl_tls.py

- -	ssl_with_bad_version = bandit.plugins.insecure_ssl_tls:ssl_with_bad_version

- -	ssl_with_bad_defaults = bandit.plugins.insecure_ssl_tls:ssl_with_bad_defaults

- -	ssl_with_no_version = bandit.plugins.insecure_ssl_tls:ssl_with_no_version

- -	# bandit/plugins/jinja2_templates.py

- -	jinja2_autoescape_false = bandit.plugins.jinja2_templates:jinja2_autoescape_false

- -	# bandit/plugins/mako_templates.py

- -	use_of_mako_templates = bandit.plugins.mako_templates:use_of_mako_templates

- -	# bandit/plugins/secret_config_options.py

- -	password_config_option_not_marked_secret = bandit.plugins.secret_config_option:password_config_option_not_marked_secret

- -	# bandit/plugins/try_except_continue.py

- -	try_except_continue = bandit.plugins.try_except_continue:try_except_continue

- -	# bandit/plugins/try_except_pass.py

- -	try_except_pass = bandit.plugins.try_except_pass:try_except_pass

- -	# bandit/plugins/weak_cryptographic_key.py

- -	weak_cryptographic_key = bandit.plugins.weak_cryptographic_key:weak_cryptographic_key

- -	# bandit/plugins/yaml_load.py

- -	yaml_load = bandit.plugins.yaml_load:yaml_load

- +console_scripts =

- +    bandit = bandit.cli.main:main

- +    bandit-config-generator = bandit.cli.config_generator:main

- +    bandit-baseline = bandit.cli.baseline:main

- +bandit.blacklists =

- +    calls = bandit.blacklists.calls:gen_blacklist

- +    imports = bandit.blacklists.imports:gen_blacklist

- +bandit.formatters =

- +    csv = bandit.formatters.csv:report

- +    json = bandit.formatters.json:report

- +    txt = bandit.formatters.text:report

- +    xml = bandit.formatters.xml:report

- +    html = bandit.formatters.html:report

- +    screen = bandit.formatters.screen:report

- +bandit.plugins =

- +    # bandit/plugins/app_debug.py

- +    flask_debug_true = bandit.plugins.app_debug:flask_debug_true

- +

- +    # bandit/plugins/asserts.py

- +    assert_used = bandit.plugins.asserts:assert_used

- +

- +    # bandit/plugins/crypto_request_no_cert_validation.py

- +    request_with_no_cert_validation = bandit.plugins.crypto_request_no_cert_validation:request_with_no_cert_validation

- +

- +    # bandit/plugins/exec_as_root.py

- +    execute_with_run_as_root_equals_true = bandit.plugins.exec_as_root:execute_with_run_as_root_equals_true

- +

- +    # bandit/plugins/exec.py

- +    exec_used = bandit.plugins.exec:exec_used

- +

- +    # bandit/plugins/general_bad_File_permissions.py

- +    set_bad_file_permissions = bandit.plugins.general_bad_file_permissions:set_bad_file_permissions

- +

- +    # bandit/plugins/general_bind_all_interfaces.py

- +    hardcoded_bind_all_interfaces = bandit.plugins.general_bind_all_interfaces:hardcoded_bind_all_interfaces

- +

- +    # bandit/plugins/general_hardcoded_password.py

- +    hardcoded_password_string = bandit.plugins.general_hardcoded_password:hardcoded_password_string

- +    hardcoded_password_funcarg = bandit.plugins.general_hardcoded_password:hardcoded_password_funcarg

- +    hardcoded_password_default = bandit.plugins.general_hardcoded_password:hardcoded_password_default

- +

- +    # bandit/plugins/general_hardcoded_tmp.py

- +    hardcoded_tmp_directory = bandit.plugins.general_hardcoded_tmp:hardcoded_tmp_directory

- +

- +    # bandit/plugins/injection_paramiko.py

- +    paramiko_calls = bandit.plugins.injection_paramiko:paramiko_calls

- +

- +    # bandit/plugins/injection_shell.py

- +    subprocess_popen_with_shell_equals_true = bandit.plugins.injection_shell:subprocess_popen_with_shell_equals_true

- +    subprocess_without_shell_equals_true = bandit.plugins.injection_shell:subprocess_without_shell_equals_true

- +    any_other_function_with_shell_equals_true = bandit.plugins.injection_shell:any_other_function_with_shell_equals_true

- +    start_process_with_a_shell = bandit.plugins.injection_shell:start_process_with_a_shell

- +    start_process_with_no_shell = bandit.plugins.injection_shell:start_process_with_no_shell

- +    start_process_with_partial_path = bandit.plugins.injection_shell:start_process_with_partial_path

- +

- +    # bandit/plugins/injection_sql.py

- +    hardcoded_sql_expressions = bandit.plugins.injection_sql:hardcoded_sql_expressions

- +

- +    # bandit/plugins/injection_wildcard.py

- +    linux_commands_wildcard_injection = bandit.plugins.injection_wildcard:linux_commands_wildcard_injection

- +

- +    # bandit/plugins/insecure_ssl_tls.py

- +    ssl_with_bad_version = bandit.plugins.insecure_ssl_tls:ssl_with_bad_version

- +    ssl_with_bad_defaults = bandit.plugins.insecure_ssl_tls:ssl_with_bad_defaults

- +    ssl_with_no_version = bandit.plugins.insecure_ssl_tls:ssl_with_no_version

- +

- +    # bandit/plugins/jinja2_templates.py

- +    jinja2_autoescape_false = bandit.plugins.jinja2_templates:jinja2_autoescape_false

- +

- +    # bandit/plugins/mako_templates.py

- +    use_of_mako_templates = bandit.plugins.mako_templates:use_of_mako_templates

- +

- +    # bandit/plugins/secret_config_options.py

- +    password_config_option_not_marked_secret = bandit.plugins.secret_config_option:password_config_option_not_marked_secret

- +

- +    # bandit/plugins/try_except_continue.py

- +    try_except_continue = bandit.plugins.try_except_continue:try_except_continue

- +

- +    # bandit/plugins/try_except_pass.py

- +    try_except_pass = bandit.plugins.try_except_pass:try_except_pass

- +

- +    # bandit/plugins/weak_cryptographic_key.py

- +    weak_cryptographic_key = bandit.plugins.weak_cryptographic_key:weak_cryptographic_key

- +

- +    # bandit/plugins/yaml_load.py

- +    yaml_load = bandit.plugins.yaml_load:yaml_load

-  

-  [build_sphinx]

-  all_files = 1

- @@ -99,9 +119,3 @@ autodoc_tree_index_modules = True

-  

-  [bdist_wheel]

-  universal = 1

- -

- -[egg_info]

- -tag_build = 

- -tag_date = 0

- -tag_svn_revision = 0

- -

@@ -1,1998 +0,0 @@ 

- From 96632b53eb20ab6e572c2f147c114a1f626df738 Mon Sep 17 00:00:00 2001

- From: Philip Jones <philip.graham.jones@gmail.com>

- Date: Fri, 30 Dec 2016 19:21:03 +0000

- Subject: [PATCH 01/43] Alter SQL Injection plugin SQL check

- 

- The previous version assumed the SQL query would start with `select`,

- `insert into`, `update` or `delete from` which rules out queries that

- are not so simple, for example queries using `with` such as:

- 

-    WITH cte AS (query)

-    SELECT something FROM cte;

- 

- This version losens the criteria and considers any string with simple

- SQL grammar (e.g. `select` followed by `from` anywhere within) as SQL.

- 

- Change-Id: I4c95842474e71aed61abc4bc878f3565a907f7c7

- ---

-  bandit/plugins/injection_sql.py     | 15 ++++++++++-----

-  examples/sql_statements.py          |  2 ++

-  tests/functional/test_functional.py |  4 ++--

-  3 files changed, 14 insertions(+), 7 deletions(-)

- 

- diff --git a/bandit/plugins/injection_sql.py b/bandit/plugins/injection_sql.py

- index 89b4e68..e284e4c 100644

- --- a/bandit/plugins/injection_sql.py

- +++ b/bandit/plugins/injection_sql.py

- @@ -60,18 +60,23 @@ If so, a MEDIUM issue is reported. For example:

-  """

-  

-  import ast

- +import re

-  

-  import bandit

-  from bandit.core import test_properties as test

-  from bandit.core import utils

-  

- +SIMPLE_SQL_RE = re.compile(

- +    r'(select\s.*from\s|'

- +    r'delete\s+from\s|'

- +    r'insert\s+into\s.*values\s|'

- +    r'update\s.*set\s)',

- +    re.IGNORECASE | re.DOTALL,

- +)

- +

-  

-  def _check_string(data):

- -    val = data.lower()

- -    return ((val.startswith('select ') and ' from ' in val) or

- -            val.startswith('insert into') or

- -            (val.startswith('update ') and ' set ' in val) or

- -            val.startswith('delete from '))

- +    return SIMPLE_SQL_RE.search(data) is not None

-  

-  

-  def _evaluate_ast(node):

- diff --git a/examples/sql_statements.py b/examples/sql_statements.py

- index 66158df..51abcff 100644

- --- a/examples/sql_statements.py

- +++ b/examples/sql_statements.py

- @@ -5,6 +5,8 @@ query = "SELECT * FROM foo WHERE id = '%s'" % identifier

-  query = "INSERT INTO foo VALUES ('a', 'b', '%s')" % value

-  query = "DELETE FROM foo WHERE id = '%s'" % identifier

-  query = "UPDATE foo SET value = 'b' WHERE id = '%s'" % identifier

- +query = """WITH cte AS (SELECT x FROM foo)

- +SELECT x FROM cte WHERE x = '%s'""" % identifier

-  

-  # bad

-  cur.execute("SELECT * FROM foo WHERE id = '%s'" % identifier)

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 5578c6a..6d22ab6 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -292,8 +292,8 @@ class FunctionalTests(testtools.TestCase):

-      def test_sql_statements(self):

-          '''Test for SQL injection through string building.'''

-          expect = {

- -            'SEVERITY': {'MEDIUM': 11},

- -            'CONFIDENCE': {'LOW': 6, 'MEDIUM': 5}}

- +            'SEVERITY': {'MEDIUM': 12},

- +            'CONFIDENCE': {'LOW': 7, 'MEDIUM': 5}}

-          self.check_example('sql_statements.py', expect)

-  

-      def test_ssl_insecure_version(self):

- -- 

- 2.13.6

- 

- From d4e213445aa4e5860936faf50f570fe00bdd0a44 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Thu, 12 Jan 2017 23:53:24 -0800

- Subject: [PATCH 02/43] Add Cryptodome to blacklist and weak ciphers/hash

- 

- As stated in the bug, the PyCryptodomex package reintroduces

- PyCrypto, but with a different namespace. Therefore Bandit should

- also include Cryptodome in its checks.

- 

- Change-Id: I6a02f97747420cedfb4523917ea0083ed5792d7a

- Closes-Bug: #1655975

- ---

-  bandit/blacklists/calls.py               | 16 +++++++++++

-  bandit/plugins/weak_cryptographic_key.py |  2 ++

-  examples/ciphers.py                      | 48 ++++++++++++++++++++++----------

-  examples/crypto-md5.py                   |  7 +++++

-  examples/weak_cryptographic_key_sizes.py | 30 +++++++++++++-------

-  tests/functional/test_functional.py      | 12 ++++----

-  6 files changed, 84 insertions(+), 31 deletions(-)

- 

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 5d9de7f..01f2ce5 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -64,6 +64,9 @@ Use of insecure MD2, MD4, or MD5 hash function.

-  |      |                     | - Crypto.Hash.MD2.new              |           |

-  |      |                     | - Crypto.Hash.MD4.new              |           |

-  |      |                     | - Crypto.Hash.MD5.new              |           |

- +|      |                     | - Cryptodome.Hash.MD2.new          |           |

- +|      |                     | - Cryptodome.Hash.MD4.new          |           |

- +|      |                     | - Cryptodome.Hash.MD5.new          |           |

-  |      |                     | - cryptography.hazmat.primitives   |           |

-  |      |                     |   .hashes.MD5                      |           |

-  +------+---------------------+------------------------------------+-----------+

- @@ -82,6 +85,11 @@ as AES.

-  |      |                     | - Crypto.Cipher.Blowfish.new       |           |

-  |      |                     | - Crypto.Cipher.DES.new            |           |

-  |      |                     | - Crypto.Cipher.XOR.new            |           |

- +|      |                     | - Cryptodome.Cipher.ARC2.new       |           |

- +|      |                     | - Cryptodome.Cipher.ARC4.new       |           |

- +|      |                     | - Cryptodome.Cipher.Blowfish.new   |           |

- +|      |                     | - Cryptodome.Cipher.DES.new        |           |

- +|      |                     | - Cryptodome.Cipher.XOR.new        |           |

-  |      |                     | - cryptography.hazmat.primitives   |           |

-  |      |                     |   .ciphers.algorithms.ARC4         |           |

-  |      |                     | - cryptography.hazmat.primitives   |           |

- @@ -313,6 +321,9 @@ def gen_blacklist():

-           'Crypto.Hash.MD2.new',

-           'Crypto.Hash.MD4.new',

-           'Crypto.Hash.MD5.new',

- +         'Cryptodome.Hash.MD2.new',

- +         'Cryptodome.Hash.MD4.new',

- +         'Cryptodome.Hash.MD5.new',

-           'cryptography.hazmat.primitives.hashes.MD5'],

-          'Use of insecure MD2, MD4, or MD5 hash function.'

-          ))

- @@ -324,6 +335,11 @@ def gen_blacklist():

-           'Crypto.Cipher.Blowfish.new',

-           'Crypto.Cipher.DES.new',

-           'Crypto.Cipher.XOR.new',

- +         'Cryptodome.Cipher.ARC2.new',

- +         'Cryptodome.Cipher.ARC4.new',

- +         'Cryptodome.Cipher.Blowfish.new',

- +         'Cryptodome.Cipher.DES.new',

- +         'Cryptodome.Cipher.XOR.new',

-           'cryptography.hazmat.primitives.ciphers.algorithms.ARC4',

-           'cryptography.hazmat.primitives.ciphers.algorithms.Blowfish',

-           'cryptography.hazmat.primitives.ciphers.algorithms.IDEA'],

- diff --git a/bandit/plugins/weak_cryptographic_key.py b/bandit/plugins/weak_cryptographic_key.py

- index 7411e2d..fba061b 100644

- --- a/bandit/plugins/weak_cryptographic_key.py

- +++ b/bandit/plugins/weak_cryptographic_key.py

- @@ -106,6 +106,8 @@ def _weak_crypto_key_size_pycrypto(context):

-      func_key_type = {

-          'Crypto.PublicKey.DSA.generate': 'DSA',

-          'Crypto.PublicKey.RSA.generate': 'RSA',

- +        'Cryptodome.PublicKey.DSA.generate': 'DSA',

- +        'Cryptodome.PublicKey.RSA.generate': 'RSA',

-      }

-      key_type = func_key_type.get(context.call_function_name_qual)

-      if key_type:

- diff --git a/examples/ciphers.py b/examples/ciphers.py

- index ff334d4..7e0762d 100644

- --- a/examples/ciphers.py

- +++ b/examples/ciphers.py

- @@ -1,8 +1,13 @@

- -from Crypto.Cipher import ARC2

- -from Crypto.Cipher import ARC4

- -from Crypto.Cipher import Blowfish

- -from Crypto.Cipher import DES

- -from Crypto.Cipher import XOR

- +from Crypto.Cipher import ARC2 as pycrypto_arc2

- +from Crypto.Cipher import ARC4 as pycrypto_arc4

- +from Crypto.Cipher import Blowfish as pycrypto_blowfish

- +from Crypto.Cipher import DES as pycrypto_des

- +from Crypto.Cipher import XOR as pycrypto_xor

- +from Cryptodome.Cipher import ARC2 as pycryptodomex_arc2

- +from Cryptodome.Cipher import ARC4 as pycryptodomex_arc4

- +from Cryptodome.Cipher import Blowfish as pycryptodomex_blowfish

- +from Cryptodome.Cipher import DES as pycryptodomex_des

- +from Cryptodome.Cipher import XOR as pycryptodomex_xor

-  from Crypto.Hash import SHA

-  from Crypto import Random

-  from Crypto.Util import Counter

- @@ -13,36 +18,49 @@ from cryptography.hazmat.backends import default_backend

-  from struct import pack

-  

-  key = b'Sixteen byte key'

- -iv = Random.new().read(ARC2.block_size)

- -cipher = ARC2.new(key, ARC2.MODE_CFB, iv)

- +iv = Random.new().read(pycrypto_arc2.block_size)

- +cipher = pycrypto_arc2.new(key, pycrypto_arc2.MODE_CFB, iv)

- +msg = iv + cipher.encrypt(b'Attack at dawn')

- +cipher = pycryptodomex_arc2.new(key, pycryptodomex_arc2.MODE_CFB, iv)

-  msg = iv + cipher.encrypt(b'Attack at dawn')

-  

-  key = b'Very long and confidential key'

-  nonce = Random.new().read(16)

-  tempkey = SHA.new(key+nonce).digest()

- -cipher = ARC4.new(tempkey)

- +cipher = pycrypto_arc4.new(tempkey)

- +msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL')

- +cipher = pycryptodomex_arc4.new(tempkey)

-  msg = nonce + cipher.encrypt(b'Open the pod bay doors, HAL')

-  

- -bs = Blowfish.block_size

- -key = b'An arbitrarily long key'

-  iv = Random.new().read(bs)

- -cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)

- +key = b'An arbitrarily long key'

-  plaintext = b'docendo discimus '

-  plen = bs - divmod(len(plaintext),bs)[1]

-  padding = [plen]*plen

-  padding = pack('b'*plen, *padding)

- +bs = pycrypto_blowfish.block_size

- +cipher = pycrypto_blowfish.new(key, pycrypto_blowfish.MODE_CBC, iv)

- +msg = iv + cipher.encrypt(plaintext + padding)

- +bs = pycryptodomex_blowfish.block_size

- +cipher = pycryptodomex_blowfish.new(key, pycryptodomex_blowfish.MODE_CBC, iv)

-  msg = iv + cipher.encrypt(plaintext + padding)

-  

-  key = b'-8B key-'

- -nonce = Random.new().read(DES.block_size/2)

- -ctr = Counter.new(DES.block_size*8/2, prefix=nonce)

- -cipher = DES.new(key, DES.MODE_CTR, counter=ctr)

-  plaintext = b'We are no longer the knights who say ni!'

- +nonce = Random.new().read(pycrypto_des.block_size/2)

- +ctr = Counter.new(pycrypto_des.block_size*8/2, prefix=nonce)

- +cipher = pycrypto_des.new(key, pycrypto_des.MODE_CTR, counter=ctr)

- +msg = nonce + cipher.encrypt(plaintext)

- +nonce = Random.new().read(pycryptodomex_des.block_size/2)

- +ctr = Counter.new(pycryptodomex_des.block_size*8/2, prefix=nonce)

- +cipher = pycryptodomex_des.new(key, pycryptodomex_des.MODE_CTR, counter=ctr)

-  msg = nonce + cipher.encrypt(plaintext)

-  

-  key = b'Super secret key'

- -cipher = XOR.new(key)

-  plaintext = b'Encrypt me'

- +cipher = pycrypto_xor.new(key)

- +msg = cipher.encrypt(plaintext)

- +cipher = pycryptodomex_xor.new(key)

-  msg = cipher.encrypt(plaintext)

-  

-  cipher = Cipher(algorithms.ARC4(key), mode=None, backend=default_backend())

- diff --git a/examples/crypto-md5.py b/examples/crypto-md5.py

- index c9dc143..d5b85c2 100644

- --- a/examples/crypto-md5.py

- +++ b/examples/crypto-md5.py

- @@ -2,6 +2,9 @@ from cryptography.hazmat.primitives import hashes

-  from Crypto.Hash import MD2 as pycrypto_md2

-  from Crypto.Hash import MD4 as pycrypto_md4

-  from Crypto.Hash import MD5 as pycrypto_md5

- +from Cryptodome.Hash import MD2 as pycryptodomex_md2

- +from Cryptodome.Hash import MD4 as pycryptodomex_md4

- +from Cryptodome.Hash import MD5 as pycryptodomex_md5

-  import hashlib

-  

-  hashlib.md5(1)

- @@ -15,4 +18,8 @@ pycrypto_md2.new()

-  pycrypto_md4.new()

-  pycrypto_md5.new()

-  

- +pycryptodomex_md2.new()

- +pycryptodomex_md4.new()

- +pycryptodomex_md5.new()

- +

-  hashes.MD5()

- diff --git a/examples/weak_cryptographic_key_sizes.py b/examples/weak_cryptographic_key_sizes.py

- index 42d8dd1..f2443b5 100644

- --- a/examples/weak_cryptographic_key_sizes.py

- +++ b/examples/weak_cryptographic_key_sizes.py

- @@ -2,8 +2,10 @@ from cryptography.hazmat import backends

-  from cryptography.hazmat.primitives.asymmetric import dsa

-  from cryptography.hazmat.primitives.asymmetric import ec

-  from cryptography.hazmat.primitives.asymmetric import rsa

- -from Crypto.PublicKey import DSA

- -from Crypto.PublicKey import RSA

- +from Crypto.PublicKey import DSA as pycrypto_dsa

- +from Crypto.PublicKey import RSA as pycrypto_rsa

- +from Cryptodome.PublicKey import DSA as pycryptodomex_dsa

- +from Cryptodome.PublicKey import RSA as pycryptodomex_rsa

-  

-  

-  # Correct

- @@ -14,8 +16,10 @@ ec.generate_private_key(curve=ec.SECP384R1,

-  rsa.generate_private_key(public_exponent=65537,

-                           key_size=2048,

-                           backend=backends.default_backend())

- -DSA.generate(bits=2048)

- -RSA.generate(bits=2048)

- +pycrypto_dsa.generate(bits=2048)

- +pycrypto_rsa.generate(bits=2048)

- +pycryptodomex_dsa.generate(bits=2048)

- +pycryptodomex_rsa.generate(bits=2048)

-  

-  # Also correct: without keyword args

-  dsa.generate_private_key(4096,

- @@ -25,8 +29,10 @@ ec.generate_private_key(ec.SECP256K1,

-  rsa.generate_private_key(3,

-                           4096,

-                           backends.default_backend())

- -DSA.generate(4096)

- -RSA.generate(4096)

- +pycrypto_dsa.generate(4096)

- +pycrypto_rsa.generate(4096)

- +pycryptodomex_dsa.generate(4096)

- +pycryptodomex_rsa.generate(4096)

-  

-  # Incorrect: weak key sizes

-  dsa.generate_private_key(key_size=1024,

- @@ -36,8 +42,10 @@ ec.generate_private_key(curve=ec.SECT163R2,

-  rsa.generate_private_key(public_exponent=65537,

-                           key_size=1024,

-                           backend=backends.default_backend())

- -DSA.generate(bits=1024)

- -RSA.generate(bits=1024)

- +pycrypto_dsa.generate(bits=1024)

- +pycrypto_rsa.generate(bits=1024)

- +pycryptodomex_dsa.generate(bits=1024)

- +pycryptodomex_rsa.generate(bits=1024)

-  

-  # Also incorrect: without keyword args

-  dsa.generate_private_key(512,

- @@ -47,8 +55,10 @@ ec.generate_private_key(ec.SECT163R2,

-  rsa.generate_private_key(3,

-                           512,

-                           backends.default_backend())

- -DSA.generate(512)

- -RSA.generate(512)

- +pycrypto_dsa.generate(512)

- +pycrypto_rsa.generate(512)

- +pycryptodomex_dsa.generate(512)

- +pycryptodomex_rsa.generate(512)

-  

-  # Don't crash when the size is variable

-  rsa.generate_private_key(public_exponent=65537,

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 5578c6a..b8b30c7 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -113,14 +113,14 @@ class FunctionalTests(testtools.TestCase):

-  

-      def test_crypto_md5(self):

-          '''Test the `hashlib.md5` example.'''

- -        expect = {'SEVERITY': {'MEDIUM': 8},

- -                  'CONFIDENCE': {'HIGH': 8}}

- +        expect = {'SEVERITY': {'MEDIUM': 11},

- +                  'CONFIDENCE': {'HIGH': 11}}

-          self.check_example('crypto-md5.py', expect)

-  

-      def test_ciphers(self):

-          '''Test the `Crypto.Cipher` example.'''

- -        expect = {'SEVERITY': {'HIGH': 8},

- -                  'CONFIDENCE': {'HIGH': 8}}

- +        expect = {'SEVERITY': {'HIGH': 13},

- +                  'CONFIDENCE': {'HIGH': 13}}

-          self.check_example('ciphers.py', expect)

-  

-      def test_cipher_modes(self):

- @@ -465,8 +465,8 @@ class FunctionalTests(testtools.TestCase):

-      def test_weak_cryptographic_key(self):

-          '''Test for weak key sizes.'''

-          expect = {

- -            'SEVERITY': {'MEDIUM': 6, 'HIGH': 4},

- -            'CONFIDENCE': {'HIGH': 10}

- +            'SEVERITY': {'MEDIUM': 8, 'HIGH': 6},

- +            'CONFIDENCE': {'HIGH': 14}

-          }

-          self.check_example('weak_cryptographic_key_sizes.py', expect)

-  

- -- 

- 2.13.6

- 

- From 6ce60806ca8a44d8a8b37050539e2b2f9a54b847 Mon Sep 17 00:00:00 2001

- From: Philip Jones <philip.graham.jones@gmail.com>

- Date: Fri, 30 Dec 2016 19:38:41 +0000

- Subject: [PATCH 03/43] Alter SQL injection plugin to consider .format strings

- 

- This considers `"{}".format()` style alongside `"%s" % ` string

- formatting for possible SQL injection vulnerabilities.

- 

- Change-Id: If7b09083bd2cc5e48e5d3fd3e8d5e6142fdb67ed

- ---

-  bandit/plugins/injection_sql.py     | 27 +++++++++++++++++++--------

-  examples/sql_statements.py          | 13 ++++++-------

-  tests/functional/test_functional.py |  4 ++--

-  3 files changed, 27 insertions(+), 17 deletions(-)

- 

- diff --git a/bandit/plugins/injection_sql.py b/bandit/plugins/injection_sql.py

- index e284e4c..afb63a5 100644

- --- a/bandit/plugins/injection_sql.py

- +++ b/bandit/plugins/injection_sql.py

- @@ -27,6 +27,7 @@ some form of string building operation. For example:

-   - "SELECT %s FROM derp;" % var

-   - "SELECT thing FROM " + tab

-   - "SELECT " + val + " FROM " + tab + ...

- + - "SELECT {} FROM derp;".format(var)

-  

-  Unless care is taken to sanitize and control the input data when building such

-  SQL statement strings, an injection attack becomes possible. If strings of this

- @@ -80,15 +81,25 @@ def _check_string(data):

-  

-  

-  def _evaluate_ast(node):

- -    if not isinstance(node.parent, ast.BinOp):

- -        return (False, "")

- -

- -    out = utils.concat_string(node, node.parent)

- -    if isinstance(out[0].parent, ast.Call):  # wrapped in "execute" call?

- +    wrapper = None

- +    statement = ''

- +

- +    if isinstance(node.parent, ast.BinOp):

- +        out = utils.concat_string(node, node.parent)

- +        wrapper = out[0].parent

- +        statement = out[1]

- +    elif (isinstance(node.parent, ast.Attribute)

- +          and node.parent.attr == 'format'):

- +        statement = node.s

- +        # Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str

- +        wrapper = node.parent.parent.parent

- +

- +    if isinstance(wrapper, ast.Call):  # wrapped in "execute" call?

-          names = ['execute', 'executemany']

- -        name = utils.get_called_name(out[0].parent)

- -        return (name in names, out[1])

- -    return (False, out[1])

- +        name = utils.get_called_name(wrapper)

- +        return (name in names, statement)

- +    else:

- +        return (False, statement)

-  

-  

-  @test.checks('Str')

- diff --git a/examples/sql_statements.py b/examples/sql_statements.py

- index 51abcff..1fabb70 100644

- --- a/examples/sql_statements.py

- +++ b/examples/sql_statements.py

- @@ -7,12 +7,18 @@ query = "DELETE FROM foo WHERE id = '%s'" % identifier

-  query = "UPDATE foo SET value = 'b' WHERE id = '%s'" % identifier

-  query = """WITH cte AS (SELECT x FROM foo)

-  SELECT x FROM cte WHERE x = '%s'""" % identifier

- +# bad alternate forms

- +query = "SELECT * FROM foo WHERE id = '" + identifier + "'"

- +query = "SELECT * FROM foo WHERE id = '{}'".format(identifier)

-  

-  # bad

-  cur.execute("SELECT * FROM foo WHERE id = '%s'" % identifier)

-  cur.execute("INSERT INTO foo VALUES ('a', 'b', '%s')" % value)

-  cur.execute("DELETE FROM foo WHERE id = '%s'" % identifier)

-  cur.execute("UPDATE foo SET value = 'b' WHERE id = '%s'" % identifier)

- +# bad alternate forms

- +cur.execute("SELECT * FROM foo WHERE id = '" + identifier + "'")

- +cur.execute("SELECT * FROM foo WHERE id = '{}'".format(identifier))

-  

-  # good

-  cur.execute("SELECT * FROM foo WHERE id = '%s'", identifier)

- @@ -20,13 +26,6 @@ cur.execute("INSERT INTO foo VALUES ('a', 'b', '%s')", value)

-  cur.execute("DELETE FROM foo WHERE id = '%s'", identifier)

-  cur.execute("UPDATE foo SET value = 'b' WHERE id = '%s'", identifier)

-  

- -# bad

- -query = "SELECT " + val + " FROM " + val +" WHERE id = " + val

- -

- -# bad

- -cur.execute("SELECT " + val + " FROM " + val +" WHERE id = " + val)

- -

- -

-  # bug: https://bugs.launchpad.net/bandit/+bug/1479625

-  def a():

-      def b():

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 1938583..afc206e 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -292,8 +292,8 @@ class FunctionalTests(testtools.TestCase):

-      def test_sql_statements(self):

-          '''Test for SQL injection through string building.'''

-          expect = {

- -            'SEVERITY': {'MEDIUM': 12},

- -            'CONFIDENCE': {'LOW': 7, 'MEDIUM': 5}}

- +            'SEVERITY': {'MEDIUM': 14},

- +            'CONFIDENCE': {'LOW': 8, 'MEDIUM': 6}}

-          self.check_example('sql_statements.py', expect)

-  

-      def test_ssl_insecure_version(self):

- -- 

- 2.13.6

- 

- From 52c4b9be68258427d8b051c1bdd5dfed94c0a3ab Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 30 Jan 2017 14:08:03 -0800

- Subject: [PATCH 04/43] Use https for references to openstack.org

- 

- The openstack.org pages now support https and our references to

- the site should by default be one signed by the organization.

- 

- Change-Id: I83d2df500e2e30047494c201a2ab39820ffd1502

- ---

-  bandit/core/docs_utils.py | 2 +-

-  bandit/formatters/html.py | 4 ++--

-  2 files changed, 3 insertions(+), 3 deletions(-)

- 

- diff --git a/bandit/core/docs_utils.py b/bandit/core/docs_utils.py

- index 171eb27..6c2a640 100644

- --- a/bandit/core/docs_utils.py

- +++ b/bandit/core/docs_utils.py

- @@ -15,7 +15,7 @@

-  # under the License.

-  

-  # where our docs are hosted

- -BASE_URL = 'http://docs.openstack.org/developer/bandit/'

- +BASE_URL = 'https://docs.openstack.org/developer/bandit/'

-  

-  

-  def get_url(bid):

- diff --git a/bandit/formatters/html.py b/bandit/formatters/html.py

- index 44917f2..04c289f 100644

- --- a/bandit/formatters/html.py

- +++ b/bandit/formatters/html.py

- @@ -125,9 +125,9 @@ This formatter outputs the issues as HTML.

-          <b>Confidence: </b>HIGH<br>

-          <b>File: </b><a href="examples/yaml_load.py"

-          target="_blank">examples/yaml_load.py</a> <br>

- -        <b>More info: </b><a href="http://docs.openstack.org/developer/bandit/

- +        <b>More info: </b><a href="https://docs.openstack.org/developer/bandit/

-          plugins/yaml_load.html" target="_blank">

- -        http://docs.openstack.org/developer/bandit/plugins/yaml_load.html</a>

- +        https://docs.openstack.org/developer/bandit/plugins/yaml_load.html</a>

-          <br>

-  

-      <div class="code">

- -- 

- 2.13.6

- 

- From e17af5cac241ef9ee72d47b90cb883d28274d5fd Mon Sep 17 00:00:00 2001

- From: Anh Tran <anhtt@vn.fujitsu.com>

- Date: Tue, 7 Feb 2017 10:12:47 +0700

- Subject: [PATCH 05/43] Typo fix: targetting => targeting

- 

- Change-Id: Iebfb2186e2824e47f57f53f9480776a9cbf67398

- ---

-  bandit/core/test_set.py | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/bandit/core/test_set.py b/bandit/core/test_set.py

- index 826b5df..2429aeb 100644

- --- a/bandit/core/test_set.py

- +++ b/bandit/core/test_set.py

- @@ -112,7 +112,7 @@ class BanditTestSet(object):

-                  plugin.plugin._config = cfg

-              for check in plugin.plugin._checks:

-                  self.tests.setdefault(check, []).append(plugin.plugin)

- -                LOG.debug('added function %s (%s) targetting %s',

- +                LOG.debug('added function %s (%s) targeting %s',

-                            plugin.name, plugin.plugin._test_id, check)

-  

-      def get_tests(self, checktype):

- -- 

- 2.13.6

- 

- From 32b4714562f3eb860d1a2afba90e0634e231fb09 Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Fri, 10 Feb 2017 05:47:05 +0000

- Subject: [PATCH 06/43] Updated from global requirements

- 

- Change-Id: I5595e1b03dee7f2fdc7402a8e056ac84a8836040

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 11b6414..9e613c6 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -11,7 +11,7 @@ testscenarios>=0.4 # Apache-2.0/BSD

-  testtools>=1.4.0 # MIT

-  oslotest>=1.10.0 # Apache-2.0

-  

- -sphinx!=1.3b1,<1.4,>=1.2.1 # BSD

- +sphinx>=1.5.1 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

-  beautifulsoup4 # MIT

-  reno>=1.8.0 # Apache-2.0

- -- 

- 2.13.6

- 

- From c924b2b12f1edf0e026e8e13a81005995e20d4fb Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 20 Feb 2017 11:20:18 -0800

- Subject: [PATCH 07/43] HTTPSConnection is secure in newer Python

- 

- In Python 2.7.9 [1] and 3.4.3 [2], the HTTPSConnection class has

- been fixed to perform all the necessary certificate and hostname

- checks by default.

- 

- Therefore, Bandit's warning is only applicable if the module is

- using older versions of Python. Even though Bandit could detect

- the version of Python used for its scan, it cannot ensure that is

- the same version used for running the said scanned module.

- 

- This patch modifies the warning message to make this clearer.

- 

- [1]: https://docs.python.org/2/library/httplib.html#httplib.HTTPSConnection

- [2]: https://docs.python.org/3.4/library/http.client.html#http.client.HTTPSConnection

- 

- Change-Id: I8105137d2cbbf0eb000729a18f43c3db443644d7

- ---

-  bandit/blacklists/calls.py | 7 ++++---

-  1 file changed, 4 insertions(+), 3 deletions(-)

- 

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 01f2ce5..4f62961 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -138,8 +138,8 @@ be reviewed.

-  B309: httpsconnection

-  ---------------------

-  

- -Use of HTTPSConnection does not provide security, see

- -https://wiki.openstack.org/wiki/OSSN/OSSN-0033

- +Use of HTTPSConnection on older versions of Python prior to 2.7.9 and 3.4.3 do

- +not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033

-  

-  +------+---------------------+------------------------------------+-----------+

-  | ID   |  Name               |  Calls                             |  Severity |

- @@ -376,7 +376,8 @@ def gen_blacklist():

-          ['httplib.HTTPSConnection',

-           'http.client.HTTPSConnection',

-           'six.moves.http_client.HTTPSConnection'],

- -        'Use of HTTPSConnection does not provide security, see '

- +        'Use of HTTPSConnection on older versions of Python prior to 2.7.9 '

- +        'and 3.4.3 do not provide security, see '

-          'https://wiki.openstack.org/wiki/OSSN/OSSN-0033'

-          ))

-  

- -- 

- 2.13.6

- 

- From 4cf3af7d4cdaeace8992a6726e20ba63d3a22018 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 20 Feb 2017 13:13:25 -0800

- Subject: [PATCH 08/43] Allow config for high and medium severity key sizes

- 

- The severity level of various key sizes of RSA, DSA, and EC are

- currently hard-coded in the weak_cryptographic_key.py itself. This

- patch allows the values to be overriden via the config file mechanism.

- 

- Change-Id: I38ad5384e0e6012818bbac10f449840de6fb14ed

- ---

-  bandit/plugins/weak_cryptographic_key.py | 40 ++++++++++++++++++++++----------

-  1 file changed, 28 insertions(+), 12 deletions(-)

- 

- diff --git a/bandit/plugins/weak_cryptographic_key.py b/bandit/plugins/weak_cryptographic_key.py

- index fba061b..1c80e64 100644

- --- a/bandit/plugins/weak_cryptographic_key.py

- +++ b/bandit/plugins/weak_cryptographic_key.py

- @@ -50,15 +50,30 @@ import bandit

-  from bandit.core import test_properties as test

-  

-  

- -def _classify_key_size(key_type, key_size):

- +def gen_config(name):

- +    if name == 'weak_cryptographic_key':

- +        return {

- +            'weak_key_size_dsa_high': 1024,

- +            'weak_key_size_dsa_medium': 2048,

- +            'weak_key_size_rsa_high': 1024,

- +            'weak_key_size_rsa_medium': 2048,

- +            'weak_key_size_ec_high': 160,

- +            'weak_key_size_ec_medium': 224,

- +        }

- +

- +

- +def _classify_key_size(config, key_type, key_size):

-      if isinstance(key_size, str):

-          # size provided via a variable - can't process it at the moment

-          return

-  

-      key_sizes = {

- -        'DSA': [(1024, bandit.HIGH), (2048, bandit.MEDIUM)],

- -        'RSA': [(1024, bandit.HIGH), (2048, bandit.MEDIUM)],

- -        'EC': [(160, bandit.HIGH), (224, bandit.MEDIUM)],

- +        'DSA': [(config['weak_key_size_dsa_high'], bandit.HIGH),

- +                (config['weak_key_size_dsa_medium'], bandit.MEDIUM)],

- +        'RSA': [(config['weak_key_size_rsa_high'], bandit.HIGH),

- +                (config['weak_key_size_rsa_medium'], bandit.MEDIUM)],

- +        'EC': [(config['weak_key_size_ec_high'], bandit.HIGH),

- +               (config['weak_key_size_ec_medium'], bandit.MEDIUM)],

-      }

-  

-      for size, level in key_sizes[key_type]:

- @@ -70,7 +85,7 @@ def _classify_key_size(key_type, key_size):

-                  (key_type, size))

-  

-  

- -def _weak_crypto_key_size_cryptography_io(context):

- +def _weak_crypto_key_size_cryptography_io(context, config):

-      func_key_type = {

-          'cryptography.hazmat.primitives.asymmetric.dsa.'

-          'generate_private_key': 'DSA',

- @@ -89,7 +104,7 @@ def _weak_crypto_key_size_cryptography_io(context):

-          key_size = (context.get_call_arg_value('key_size') or

-                      context.get_call_arg_at_position(arg_position[key_type]) or

-                      2048)

- -        return _classify_key_size(key_type, key_size)

- +        return _classify_key_size(config, key_type, key_size)

-      elif key_type == 'EC':

-          curve_key_sizes = {

-              'SECP192R1': 192,

- @@ -99,10 +114,10 @@ def _weak_crypto_key_size_cryptography_io(context):

-          curve = (context.get_call_arg_value('curve') or

-                   context.call_args[arg_position[key_type]])

-          key_size = curve_key_sizes[curve] if curve in curve_key_sizes else 224

- -        return _classify_key_size(key_type, key_size)

- +        return _classify_key_size(config, key_type, key_size)

-  

-  

- -def _weak_crypto_key_size_pycrypto(context):

- +def _weak_crypto_key_size_pycrypto(context, config):

-      func_key_type = {

-          'Crypto.PublicKey.DSA.generate': 'DSA',

-          'Crypto.PublicKey.RSA.generate': 'RSA',

- @@ -114,11 +129,12 @@ def _weak_crypto_key_size_pycrypto(context):

-          key_size = (context.get_call_arg_value('bits') or

-                      context.get_call_arg_at_position(0) or

-                      2048)

- -        return _classify_key_size(key_type, key_size)

- +        return _classify_key_size(config, key_type, key_size)

-  

-  

- +@test.takes_config

-  @test.checks('Call')

-  @test.test_id('B505')

- -def weak_cryptographic_key(context):

- -    return (_weak_crypto_key_size_cryptography_io(context) or

- -            _weak_crypto_key_size_pycrypto(context))

- +def weak_cryptographic_key(context, config):

- +    return (_weak_crypto_key_size_cryptography_io(context, config) or

- +            _weak_crypto_key_size_pycrypto(context, config))

- -- 

- 2.13.6

- 

- From a38056fafaead26e1b7198523b20f323130fa262 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 20 Feb 2017 13:42:59 -0800

- Subject: [PATCH 09/43] Dump bandit config file lists vertically

- 

- Currently when using the bandit-config-generator to dump out a

- config file, it looks rather messy because config option values

- that are lists are dumped onto one long line.

- 

- So rather than dumping on one line, use the vertical yaml list

- format by specifying default_flow_style=False.

- 

- Change-Id: Ic0dc97f19d067471b507421dcb98ac749874e49c

- ---

-  bandit/cli/config_generator.py          | 2 +-

-  tests/unit/cli/test_config_generator.py | 3 ++-

-  2 files changed, 3 insertions(+), 2 deletions(-)

- 

- diff --git a/bandit/cli/config_generator.py b/bandit/cli/config_generator.py

- index e5d232c..a48c518 100644

- --- a/bandit/cli/config_generator.py

- +++ b/bandit/cli/config_generator.py

- @@ -124,7 +124,7 @@ def get_config_settings():

-              if hasattr(fn_module, 'gen_config'):

-                  config[fn_name] = fn_module.gen_config(function._takes_config)

-  

- -    return yaml.safe_dump(config)

- +    return yaml.safe_dump(config, default_flow_style=False)

-  

-  

-  def main():

- diff --git a/tests/unit/cli/test_config_generator.py b/tests/unit/cli/test_config_generator.py

- index f85c0a9..1431ab5 100644

- --- a/tests/unit/cli/test_config_generator.py

- +++ b/tests/unit/cli/test_config_generator.py

- @@ -85,7 +85,8 @@ class BanditConfigGeneratorTests(testtools.TestCase):

-                  config[plugin.name] = module.gen_config(

-                      function._takes_config)

-          settings = config_generator.get_config_settings()

- -        self.assertEqual(yaml.safe_dump(config), settings)

- +        self.assertEqual(yaml.safe_dump(config, default_flow_style=False),

- +                         settings)

-  

-      @mock.patch('sys.argv', ['bandit-config-generator', '--show-defaults'])

-      def test_main_show_defaults(self):

- -- 

- 2.13.6

- 

- From 87c8b70e7bad5484e3ed9b17c9790108c151dee5 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Thu, 23 Feb 2017 13:29:38 -0800

- Subject: [PATCH 10/43] Refactor check_example to be clearer on error

- 

- Currently the check_example in test_functional computes sums and

- on error tells the developer the difference in sums, which is

- confusing and error prone.

- 

- It also leads to false positives where sums may be correct, but

- the exact number of MEDIUM, HIGH, etc is different. This was the

- case for two tests: test_xml and test_secret_config_option.

- 

- The general_hardcoded_password test was also broken for py35

- because it was assuming function args are ast.Name not ast.arg.

- But surprisingly the tests passed because of a syntax error in

- the example.

- 

- Change-Id: Icd06fb7ca27a8a01d6442f199775d474d436371b

- ---

-  bandit/plugins/general_hardcoded_password.py |   2 +-

-  examples/hardcoded-passwords.py              |  10 +-

-  tests/functional/test_functional.py          | 340 +++++++++++++++++++--------

-  3 files changed, 247 insertions(+), 105 deletions(-)

- 

- diff --git a/bandit/plugins/general_hardcoded_password.py b/bandit/plugins/general_hardcoded_password.py

- index 97e3966..e9f7c3a 100644

- --- a/bandit/plugins/general_hardcoded_password.py

- +++ b/bandit/plugins/general_hardcoded_password.py

- @@ -209,7 +209,7 @@ def hardcoded_password_default(context):

-  

-      # go through all (param, value)s and look for candidates

-      for key, val in zip(context.node.args.args, defs):

- -        if isinstance(key, ast.Name):

- +        if isinstance(key, ast.Name) or isinstance(key, ast.arg):

-              check = key.arg if sys.version_info.major > 2 else key.id  # Py3

-              if isinstance(val, ast.Str) and check in CANDIDATES:

-                  return _report(val.s)

- diff --git a/examples/hardcoded-passwords.py b/examples/hardcoded-passwords.py

- index b59794e..221c8f4 100644

- --- a/examples/hardcoded-passwords.py

- +++ b/examples/hardcoded-passwords.py

- @@ -13,10 +13,12 @@ def NoMatch2(password):

-      if password == "ajklawejrkl42348swfgkg":

-          print("Nice password!")

-  

- +def doLogin(password="blerg"):

- +    pass

- +

- +def NoMatch3(a, b):

- +    pass

- +

-  doLogin(password="blerg")

-  password = "blerg"

-  d["password"] = "blerg"

- -

- -

- -def NoMatch3((a, b)):

- -    pass

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index afc206e..5667001 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -69,17 +69,20 @@ class FunctionalTests(testtools.TestCase):

-          # reset scores for subsequent calls to check_example

-          self.b_mgr.scores = []

-          self.run_example(example_script, ignore_nosec=ignore_nosec)

- -        expected = 0

- -        result = 0

- +

- +        result = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}

- +        }

- +

-          for test_scores in self.b_mgr.scores:

-              for score_type in test_scores:

-                  self.assertIn(score_type, expect)

- -                for rating in expect[score_type]:

- -                    expected += (

- -                        expect[score_type][rating] * C.RANKING_VALUES[rating]

- -                    )

- -                result += sum(test_scores[score_type])

- -        self.assertEqual(expected, result)

- +                for idx, rank in enumerate(C.RANKING):

- +                    result[score_type][rank] = (test_scores[score_type][idx] /

- +                                                C.RANKING_VALUES[rank])

- +

- +        self.assertDictEqual(expect, result)

-  

-      def check_metrics(self, example_script, expect):

-          '''A helper method to test the metrics being returned.

- @@ -108,34 +111,50 @@ class FunctionalTests(testtools.TestCase):

-  

-      def test_binding(self):

-          '''Test the bind-to-0.0.0.0 example.'''

- -        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'MEDIUM': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0}

- +        }

-          self.check_example('binding.py', expect)

-  

-      def test_crypto_md5(self):

-          '''Test the `hashlib.md5` example.'''

- -        expect = {'SEVERITY': {'MEDIUM': 11},

- -                  'CONFIDENCE': {'HIGH': 11}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 11, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 11}

- +        }

-          self.check_example('crypto-md5.py', expect)

-  

-      def test_ciphers(self):

-          '''Test the `Crypto.Cipher` example.'''

- -        expect = {'SEVERITY': {'HIGH': 13},

- -                  'CONFIDENCE': {'HIGH': 13}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 13},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 13}

- +        }

-          self.check_example('ciphers.py', expect)

-  

-      def test_cipher_modes(self):

-          '''Test for insecure cipher modes.'''

- -        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('cipher-modes.py', expect)

-  

-      def test_eval(self):

-          '''Test the `eval` example.'''

- -        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('eval.py', expect)

-  

-      def test_mark_safe(self):

-          '''Test the `mark_safe` example.'''

- -        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('mark_safe.py', expect)

-  

-      def test_exec(self):

- @@ -143,68 +162,106 @@ class FunctionalTests(testtools.TestCase):

-          filename = 'exec-{}.py'

-          if six.PY2:

-              filename = filename.format('py2')

- -            expect = {'SEVERITY': {'MEDIUM': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +            expect = {

- +                'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0},

- +                'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0,

- +                               'HIGH': 2}

- +            }

-          else:

-              filename = filename.format('py3')

- -            expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}

- +            expect = {

- +                'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +                'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0,

- +                               'HIGH': 1}

- +            }

-          self.check_example(filename, expect)

-  

-      def test_exec_as_root(self):

-          '''Test for the `run_as_root=True` keyword argument.'''

- -        expect = {'SEVERITY': {'LOW': 5}, 'CONFIDENCE': {'MEDIUM': 5}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 5, 'HIGH': 0}

- +        }

-          self.check_example('exec-as-root.py', expect)

-  

-      def test_hardcoded_passwords(self):

-          '''Test for hard-coded passwords.'''

- -        expect = {'SEVERITY': {'LOW': 7}, 'CONFIDENCE': {'MEDIUM': 7}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}

- +        }

-          self.check_example('hardcoded-passwords.py', expect)

-  

-      def test_hardcoded_tmp(self):

-          '''Test for hard-coded /tmp, /var/tmp, /dev/shm.'''

- -        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'MEDIUM': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0}

- +        }

-          self.check_example('hardcoded-tmp.py', expect)

-  

-      def test_httplib_https(self):

-          '''Test for `httplib.HTTPSConnection`.'''

- -        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('httplib_https.py', expect)

-  

-      def test_imports_aliases(self):

-          '''Test the `import X as Y` syntax.'''

-          expect = {

- -            'SEVERITY': {'LOW': 4, 'MEDIUM': 5, 'HIGH': 0},

- -            'CONFIDENCE': {'HIGH': 9}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 4, 'MEDIUM': 5, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 9}

-          }

-          self.check_example('imports-aliases.py', expect)

-  

-      def test_imports_from(self):

-          '''Test the `from X import Y` syntax.'''

- -        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('imports-from.py', expect)

-  

-      def test_imports_function(self):

-          '''Test the `__import__` function.'''

- -        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('imports-function.py', expect)

-  

-      def test_telnet_usage(self):

-          '''Test for `import telnetlib` and Telnet.* calls.'''

- -        expect = {'SEVERITY': {'HIGH': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('telnetlib.py', expect)

-  

-      def test_ftp_usage(self):

-          '''Test for `import ftplib` and FTP.* calls.'''

- -        expect = {'SEVERITY': {'HIGH': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('ftplib.py', expect)

-  

-      def test_imports(self):

-          '''Test for dangerous imports.'''

- -        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('imports.py', expect)

-  

-      def test_mktemp(self):

-          '''Test for `tempfile.mktemp`.'''

- -        expect = {'SEVERITY': {'MEDIUM': 4}, 'CONFIDENCE': {'HIGH': 4}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 4, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}

- +        }

-          self.check_example('mktemp.py', expect)

-  

-      def test_nonsense(self):

- @@ -214,7 +271,10 @@ class FunctionalTests(testtools.TestCase):

-  

-      def test_okay(self):

-          '''Test a vulnerability-free file.'''

- -        expect = {'SEVERITY': {}, 'CONFIDENCE': {}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}

- +        }

-          self.check_example('okay.py', expect)

-  

-      def test_os_chmod(self):

- @@ -225,75 +285,105 @@ class FunctionalTests(testtools.TestCase):

-          else:

-              filename = filename.format('py3')

-          expect = {

- -            'SEVERITY': {'MEDIUM': 2, 'HIGH': 8},

- -            'CONFIDENCE': {'MEDIUM': 1, 'HIGH': 9}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 8},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 9}

-          }

-          self.check_example(filename, expect)

-  

-      def test_os_exec(self):

-          '''Test for `os.exec*`.'''

- -        expect = {'SEVERITY': {'LOW': 8}, 'CONFIDENCE': {'MEDIUM': 8}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}

- +        }

-          self.check_example('os-exec.py', expect)

-  

-      def test_os_popen(self):

-          '''Test for `os.popen`.'''

- -        expect = {'SEVERITY': {'LOW': 8, 'MEDIUM': 0, 'HIGH': 1},

- -                  'CONFIDENCE': {'HIGH': 9}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 1},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 9}

- +        }

-          self.check_example('os-popen.py', expect)

-  

-      def test_os_spawn(self):

-          '''Test for `os.spawn*`.'''

- -        expect = {'SEVERITY': {'LOW': 8}, 'CONFIDENCE': {'MEDIUM': 8}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}

- +        }

-          self.check_example('os-spawn.py', expect)

-  

-      def test_os_startfile(self):

-          '''Test for `os.startfile`.'''

- -        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'MEDIUM': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0}

- +        }

-          self.check_example('os-startfile.py', expect)

-  

-      def test_os_system(self):

-          '''Test for `os.system`.'''

- -        expect = {'SEVERITY': {'LOW': 1}, 'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('os_system.py', expect)

-  

-      def test_pickle(self):

-          '''Test for the `pickle` module.'''

-          expect = {

- -            'SEVERITY': {'LOW': 2, 'MEDIUM': 6},

- -            'CONFIDENCE': {'HIGH': 8}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 6, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 8}

-          }

-          self.check_example('pickle_deserialize.py', expect)

-  

-      def test_popen_wrappers(self):

-          '''Test the `popen2` and `commands` modules.'''

- -        expect = {'SEVERITY': {'LOW': 7}, 'CONFIDENCE': {'HIGH': 7}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 7, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}

- +        }

-          self.check_example('popen_wrappers.py', expect)

-  

-      def test_random_module(self):

-          '''Test for the `random` module.'''

- -        expect = {'SEVERITY': {'LOW': 6}, 'CONFIDENCE': {'HIGH': 6}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 6, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 6}

- +        }

-          self.check_example('random_module.py', expect)

-  

-      def test_requests_ssl_verify_disabled(self):

-          '''Test for the `requests` library skipping verification.'''

- -        expect = {'SEVERITY': {'HIGH': 7}, 'CONFIDENCE': {'HIGH': 7}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}

- +        }

-          self.check_example('requests-ssl-verify-disabled.py', expect)

-  

-      def test_skip(self):

-          '''Test `#nosec` and `#noqa` comments.'''

- -        expect = {'SEVERITY': {'LOW': 5}, 'CONFIDENCE': {'HIGH': 5}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}

- +        }

-          self.check_example('skip.py', expect)

-  

-      def test_ignore_skip(self):

-          '''Test --ignore-nosec flag.'''

- -        expect = {'SEVERITY': {'LOW': 7}, 'CONFIDENCE': {'HIGH': 7}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 7, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}

- +        }

-          self.check_example('skip.py', expect, ignore_nosec=True)

-  

-      def test_sql_statements(self):

-          '''Test for SQL injection through string building.'''

-          expect = {

- -            'SEVERITY': {'MEDIUM': 14},

- -            'CONFIDENCE': {'LOW': 8, 'MEDIUM': 6}}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 14, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 6, 'HIGH': 0}

- +        }

-          self.check_example('sql_statements.py', expect)

-  

-      def test_ssl_insecure_version(self):

- @@ -302,126 +392,164 @@ class FunctionalTests(testtools.TestCase):

-              'SEVERITY': {'LOW': 1, 'MEDIUM': 10, 'HIGH': 7},

-              'CONFIDENCE': {'LOW': 0, 'MEDIUM': 11, 'HIGH': 7}

-          }

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 10, 'HIGH': 7},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 11, 'HIGH': 7}

- +        }

-          self.check_example('ssl-insecure-version.py', expect)

-  

-      def test_subprocess_shell(self):

-          '''Test for `subprocess.Popen` with `shell=True`.'''

-          expect = {

- -            'SEVERITY': {'HIGH': 3, 'MEDIUM': 1, 'LOW': 14},

- -            'CONFIDENCE': {'HIGH': 17, 'LOW': 1}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 14, 'MEDIUM': 1, 'HIGH': 3},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 17}

-          }

-          self.check_example('subprocess_shell.py', expect)

-  

-      def test_urlopen(self):

-          '''Test for dangerous URL opening.'''

- -        expect = {'SEVERITY': {'MEDIUM': 14}, 'CONFIDENCE': {'HIGH': 14}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 14, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}

- +        }

-          self.check_example('urlopen.py', expect)

-  

-      def test_utils_shell(self):

-          '''Test for `utils.execute*` with `shell=True`.'''

-          expect = {

- -            'SEVERITY': {'LOW': 5},

- -            'CONFIDENCE': {'HIGH': 5}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}

-          }

-          self.check_example('utils-shell.py', expect)

-  

-      def test_wildcard_injection(self):

-          '''Test for wildcard injection in shell commands.'''

-          expect = {

- -            'SEVERITY': {'HIGH': 4, 'MEDIUM': 0, 'LOW': 10},

- -            'CONFIDENCE': {'MEDIUM': 5, 'HIGH': 9}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 10, 'MEDIUM': 0, 'HIGH': 4},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 5, 'HIGH': 9}

-          }

-          self.check_example('wildcard-injection.py', expect)

-  

-      def test_yaml(self):

-          '''Test for `yaml.load`.'''

- -        expect = {'SEVERITY': {'MEDIUM': 1}, 'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('yaml_load.py', expect)

-  

-      def test_jinja2_templating(self):

-          '''Test jinja templating for potential XSS bugs.'''

-          expect = {

- -            'SEVERITY': {'HIGH': 4},

- -            'CONFIDENCE': {'HIGH': 3, 'MEDIUM': 1}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 3}

-          }

-          self.check_example('jinja2_templating.py', expect)

-  

-      def test_secret_config_option(self):

-          '''Test for `secret=True` in Oslo's config.'''

-          expect = {

- -            'SEVERITY': {'LOW': 1, 'MEDIUM': 2},

- -            'CONFIDENCE': {'MEDIUM': 3}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 2, 'HIGH': 0}

-          }

-          self.check_example('secret-config-option.py', expect)

-  

-      def test_mako_templating(self):

-          '''Test Mako templates for XSS.'''

- -        expect = {'SEVERITY': {'MEDIUM': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('mako_templating.py', expect)

-  

-      def test_xml(self):

-          '''Test xml vulnerabilities.'''

- -        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 4},

- -                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 4}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 4, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}

- +        }

-          self.check_example('xml_etree_celementtree.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 2},

- -                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 2, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('xml_expatbuilder.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 3, 'HIGH': 1},

- -                  'CONFIDENCE': {'HIGH': 3, 'MEDIUM': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}

- +        }

-          self.check_example('xml_lxml.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 2, 'HIGH': 2},

- -                  'CONFIDENCE': {'HIGH': 2, 'MEDIUM': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 2, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}

- +        }

-          self.check_example('xml_pulldom.py', expect)

-  

- -        expect = {'SEVERITY': {'HIGH': 1},

- -                  'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('xml_xmlrpc.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 4},

- -                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 4}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 4, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}

- +        }

-          self.check_example('xml_etree_elementtree.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 1, 'HIGH': 1},

- -                  'CONFIDENCE': {'HIGH': 1, 'MEDIUM': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('xml_expatreader.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 2, 'HIGH': 2},

- -                  'CONFIDENCE': {'HIGH': 2, 'MEDIUM': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 2, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}

- +        }

-          self.check_example('xml_minidom.py', expect)

-  

- -        expect = {'SEVERITY': {'LOW': 2, 'HIGH': 6},

- -                  'CONFIDENCE': {'HIGH': 2, 'MEDIUM': 6}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 6, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 8}

- +        }

-          self.check_example('xml_sax.py', expect)

-  

-      def test_httpoxy(self):

-          '''Test httpoxy vulnerability.'''

- -        expect = {'SEVERITY': {'HIGH': 1},

- -                  'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('httpoxy_cgihandler.py', expect)

-          self.check_example('httpoxy_twisted_script.py', expect)

-          self.check_example('httpoxy_twisted_directory.py', expect)

-  

-      def test_asserts(self):

-          '''Test catching the use of assert.'''

- -        expect = {'SEVERITY': {'LOW': 1},

- -                  'CONFIDENCE': {'HIGH': 1}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

-          self.check_example('assert.py', expect)

-  

-      def test_paramiko_injection(self):

-          '''Test paramiko command execution.'''

- -        expect = {'SEVERITY': {'MEDIUM': 2},

- -                  'CONFIDENCE': {'MEDIUM': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0}

- +        }

-          self.check_example('paramiko_injection.py', expect)

-  

-      def test_partial_path(self):

-          '''Test process spawning with partial file paths.'''

- -        expect = {'SEVERITY': {'LOW': 11},

- -                  'CONFIDENCE': {'HIGH': 11}}

- -

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 11, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 11}

- +        }

-          self.check_example('partial_path_process.py', expect)

-  

-      def test_try_except_continue(self):

- @@ -430,11 +558,17 @@ class FunctionalTests(testtools.TestCase):

-                      if x.__name__ == 'try_except_continue'))

-  

-          test._config = {'check_typed_exception': True}

- -        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('try_except_continue.py', expect)

-  

-          test._config = {'check_typed_exception': False}

- -        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('try_except_continue.py', expect)

-  

-      def test_try_except_pass(self):

- @@ -443,11 +577,17 @@ class FunctionalTests(testtools.TestCase):

-                       if x.__name__ == 'try_except_pass'))

-  

-          test._config = {'check_typed_exception': True}

- -        expect = {'SEVERITY': {'LOW': 3}, 'CONFIDENCE': {'HIGH': 3}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}

- +        }

-          self.check_example('try_except_pass.py', expect)

-  

-          test._config = {'check_typed_exception': False}

- -        expect = {'SEVERITY': {'LOW': 2}, 'CONFIDENCE': {'HIGH': 2}}

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}

- +        }

-          self.check_example('try_except_pass.py', expect)

-  

-      def test_metric_gathering(self):

- @@ -465,8 +605,8 @@ class FunctionalTests(testtools.TestCase):

-      def test_weak_cryptographic_key(self):

-          '''Test for weak key sizes.'''

-          expect = {

- -            'SEVERITY': {'MEDIUM': 8, 'HIGH': 6},

- -            'CONFIDENCE': {'HIGH': 14}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 6},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}

-          }

-          self.check_example('weak_cryptographic_key_sizes.py', expect)

-  

- @@ -503,15 +643,15 @@ class FunctionalTests(testtools.TestCase):

-  

-      def test_flask_debug_true(self):

-          expect = {

- -            'SEVERITY': {'HIGH': 1},

- -            'CONFIDENCE': {'MEDIUM': 1}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0}

-          }

-          self.check_example('flask_debug.py', expect)

-  

-      def test_nosec(self):

-          expect = {

- -            'SEVERITY': {},

- -            'CONFIDENCE': {}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}

-          }

-          self.check_example('nosec.py', expect)

-  

- @@ -545,7 +685,7 @@ class FunctionalTests(testtools.TestCase):

-  

-      def test_blacklist_input(self):

-          expect = {

- -            'SEVERITY': {'HIGH': 1},

- -            'CONFIDENCE': {'HIGH': 1}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

-          }

-          self.check_example('input.py', expect)

- -- 

- 2.13.6

- 

- From 35e35446b00bceea5bebf028567e4f99bd29dc98 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Thu, 23 Feb 2017 11:05:04 -0800

- Subject: [PATCH 11/43] Add sha-1 to list of insecure hashes

- 

- With the news of a first collison implemented [1], bandit should

- now start blacklisting the use of sha-1.

- 

- The sha-1 hash was added to the existing blacklist check B303 which

- currently checks for MD5 and variants.

- 

- [1]: https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html

- 

- Change-Id: I411d8d4aeb4d740635c60b559ecda72ab951b629

- ---

-  bandit/blacklists/calls.py          | 15 ++++++++++++---

-  examples/crypto-md5.py              |  7 +++++++

-  tests/functional/test_functional.py |  8 ++++----

-  3 files changed, 23 insertions(+), 7 deletions(-)

- 

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 01f2ce5..78b029c 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -55,20 +55,25 @@ Deserialization with the marshal module is possibly dangerous.

-  B303: md5

-  ---------

-  

- -Use of insecure MD2, MD4, or MD5 hash function.

- +Use of insecure MD2, MD4, MD5, or SHA1 hash function.

-  

-  +------+---------------------+------------------------------------+-----------+

-  | ID   |  Name               |  Calls                             |  Severity |

-  +======+=====================+====================================+===========+

-  | B303 | md5                 | - hashlib.md5                      | Medium    |

- +|      |                     | - hashlib.sha1                     |           |

-  |      |                     | - Crypto.Hash.MD2.new              |           |

-  |      |                     | - Crypto.Hash.MD4.new              |           |

-  |      |                     | - Crypto.Hash.MD5.new              |           |

- +|      |                     | - Crypto.Hash.SHA.new              |           |

-  |      |                     | - Cryptodome.Hash.MD2.new          |           |

-  |      |                     | - Cryptodome.Hash.MD4.new          |           |

-  |      |                     | - Cryptodome.Hash.MD5.new          |           |

- +|      |                     | - Cryptodome.Hash.SHA.new          |           |

-  |      |                     | - cryptography.hazmat.primitives   |           |

-  |      |                     |   .hashes.MD5                      |           |

- +|      |                     | - cryptography.hazmat.primitives   |           |

- +|      |                     |   .hashes.SHA1                     |           |

-  +------+---------------------+------------------------------------+-----------+

-  

-  B304 - B305: ciphers and modes

- @@ -318,14 +323,18 @@ def gen_blacklist():

-      sets.append(utils.build_conf_dict(

-          'md5', 'B303',

-          ['hashlib.md5',

- +         'hashlib.sha1',

-           'Crypto.Hash.MD2.new',

-           'Crypto.Hash.MD4.new',

-           'Crypto.Hash.MD5.new',

- +         'Crypto.Hash.SHA.new',

-           'Cryptodome.Hash.MD2.new',

-           'Cryptodome.Hash.MD4.new',

-           'Cryptodome.Hash.MD5.new',

- -         'cryptography.hazmat.primitives.hashes.MD5'],

- -        'Use of insecure MD2, MD4, or MD5 hash function.'

- +         'Cryptodome.Hash.SHA.new',

- +         'cryptography.hazmat.primitives.hashes.MD5',

- +         'cryptography.hazmat.primitives.hashes.SHA1'],

- +        'Use of insecure MD2, MD4, MD5, or SHA1 hash function.'

-          ))

-  

-      sets.append(utils.build_conf_dict(

- diff --git a/examples/crypto-md5.py b/examples/crypto-md5.py

- index d5b85c2..045740c 100644

- --- a/examples/crypto-md5.py

- +++ b/examples/crypto-md5.py

- @@ -2,9 +2,11 @@ from cryptography.hazmat.primitives import hashes

-  from Crypto.Hash import MD2 as pycrypto_md2

-  from Crypto.Hash import MD4 as pycrypto_md4

-  from Crypto.Hash import MD5 as pycrypto_md5

- +from Crypto.Hash import SHA as pycrypto_sha

-  from Cryptodome.Hash import MD2 as pycryptodomex_md2

-  from Cryptodome.Hash import MD4 as pycryptodomex_md4

-  from Cryptodome.Hash import MD5 as pycryptodomex_md5

- +from Cryptodome.Hash import SHA as pycryptodomex_sha

-  import hashlib

-  

-  hashlib.md5(1)

- @@ -14,12 +16,17 @@ abc = str.replace(hashlib.md5("1"), "###")

-  

-  print(hashlib.md5("1"))

-  

- +hashlib.sha1(1)

- +

-  pycrypto_md2.new()

-  pycrypto_md4.new()

-  pycrypto_md5.new()

- +pycrypto_sha.new()

-  

-  pycryptodomex_md2.new()

-  pycryptodomex_md4.new()

-  pycryptodomex_md5.new()

- +pycryptodomex_sha.new()

-  

-  hashes.MD5()

- +hashes.SHA1()

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 5667001..e94c3bf 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -120,16 +120,16 @@ class FunctionalTests(testtools.TestCase):

-      def test_crypto_md5(self):

-          '''Test the `hashlib.md5` example.'''

-          expect = {

- -            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 11, 'HIGH': 0},

- -            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 11}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 15, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 15}

-          }

-          self.check_example('crypto-md5.py', expect)

-  

-      def test_ciphers(self):

-          '''Test the `Crypto.Cipher` example.'''

-          expect = {

- -            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 13},

- -            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 13}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 13},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}

-          }

-          self.check_example('ciphers.py', expect)

-  

- -- 

- 2.13.6

- 

- From 6a1a4b120d005cee2ed0c8be723dd367b549b3f0 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 27 Feb 2017 15:48:44 -0800

- Subject: [PATCH 12/43] Docs for B319 listed twice

- 

- The blacklist calls doc lists B319 twice. This patch removes the

- duplicate.

- 

- [1]: https://docs.openstack.org/developer/bandit/blacklists/blacklist_calls.html#b313-b320-xml

- 

- Change-Id: I94ca7cb1201f6d74ce8672294d2ba421ea5a608c

- ---

-  bandit/blacklists/calls.py | 3 ---

-  1 file changed, 3 deletions(-)

- 

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 01f2ce5..9928f59 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -244,9 +244,6 @@ to XML attacks. Methods should be replaced with their defusedxml equivalents.

-  | B319 | xml_bad_pulldom     | - xml.dom.pulldom.parse            | Medium    |

-  |      |                     | - xml.dom.pulldom.parseString      |           |

-  +------+---------------------+------------------------------------+-----------+

- -| B319 | xml_bad_pulldom     | - xml.dom.pulldom.parse            | Medium    |

- -|      |                     | - xml.dom.pulldom.parseString      |           |

- -+------+---------------------+------------------------------------+-----------+

-  | B320 | xml_bad_etree       | - lxml.etree.parse                 | Medium    |

-  |      |                     | - lxml.etree.fromstring            |           |

-  |      |                     | - lxml.etree.RestrictedElement     |           |

- -- 

- 2.13.6

- 

- From be0483a603407ba8f8110da415161cee26f142b8 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 27 Feb 2017 15:44:02 -0800

- Subject: [PATCH 13/43] Repair the more info links for two blacklist calls

- 

- The blacklist calls has some of documentation anchors combined [1].

- As a result, the links don't correct point to the proper anchor in

- the html. Therefore we need some exception cases for checks that

- have doc combined. Namely B304-B305 and B313-B320.

- 

- This patch also fixes links where there is an underscore in the

- plugin name and replaces it with a dash. Apparently sphinx will

- substitute _ for - when building the doc anchors.

- 

- [1]: https://docs.openstack.org/developer/bandit/blacklists/blacklist_calls.html#b304-b305-ciphers-and-modes

- 

- Change-Id: I4dfa905425f2631fa488a9a066c427d4145f4aac

- ---

-  bandit/core/docs_utils.py | 9 +++++++++

-  1 file changed, 9 insertions(+)

- 

- diff --git a/bandit/core/docs_utils.py b/bandit/core/docs_utils.py

- index 6c2a640..8f268e0 100644

- --- a/bandit/core/docs_utils.py

- +++ b/bandit/core/docs_utils.py

- @@ -31,7 +31,16 @@ def get_url(bid):

-      info = extension_loader.MANAGER.blacklist_by_id.get(bid, None)

-      if info is not None:

-          template = 'blacklists/blacklist_{kind}.html#{id}-{name}'

- +        info['name'] = info['name'].replace('_', '-')

- +

-          if info['id'].startswith('B3'):  # B3XX

- +            # Some of the links are combined, so we have exception cases

- +            if info['id'] in ['B304', 'B305']:

- +                info['id'] = 'b304-b305'

- +                info['name'] = 'ciphers-and-modes'

- +            elif info['id'] in ['B313', 'B314', 'B315', 'B316', 'B317',

- +                                'B318', 'B319', 'B320']:

- +                info['id'] = 'b313-b320'

-              ext = template.format(

-                  kind='calls', id=info['id'], name=info['name'])

-          else:

- -- 

- 2.13.6

- 

- From fbd4e83efe15987f4f8a4608456211fba37fc80b Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Wed, 22 Feb 2017 20:28:19 -0800

- Subject: [PATCH 14/43] Yet Another Formatter (yaml)

- 

- This patch adds a yaml formatter to the output options of bandit.

- 

- Change-Id: Ibbe0cff062ce2c11138b746f95109f31de10f5b1

- ---

-  README.rst                         |  6 +--

-  bandit/formatters/yaml.py          | 92 ++++++++++++++++++++++++++++++++++++

-  doc/source/formatters/yaml.rst     |  5 ++

-  doc/source/man/bandit.rst          |  6 +--

-  setup.cfg                          |  1 +

-  tests/unit/formatters/test_yaml.py | 96 ++++++++++++++++++++++++++++++++++++++

-  6 files changed, 200 insertions(+), 6 deletions(-)

-  create mode 100644 bandit/formatters/yaml.py

-  create mode 100644 doc/source/formatters/yaml.rst

-  create mode 100644 tests/unit/formatters/test_yaml.py

- 

- diff --git a/README.rst b/README.rst

- index 61a5e7b..b7f4ba9 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -87,8 +87,8 @@ Usage::

-      $ bandit -h

-      usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]

-                    [-p PROFILE] [-t TESTS] [-s SKIPS] [-l] [-i]

- -                  [-f {csv,html,json,screen,txt,xml}] [-o [OUTPUT_FILE]] [-v] [-d]

- -                  [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

- +                  [-f {csv,html,json,screen,txt,xml,yaml}] [-o [OUTPUT_FILE]] [-v]

- +                  [-d] [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

-                    [--ini INI_PATH] [--version]

-                    targets [targets ...]

-  

- @@ -118,7 +118,7 @@ Usage::

-                              (-l for LOW, -ll for MEDIUM, -lll for HIGH)

-        -i, --confidence      report only issues of a given confidence level or

-                              higher (-i for LOW, -ii for MEDIUM, -iii for HIGH)

- -      -f {csv,html,json,screen,txt,xml}, --format {csv,html,json,screen,txt,xml}

- +      -f {csv,html,json,screen,txt,xml,yaml}, --format {csv,html,json,screen,txt,xml,yaml}

-                              specify output format

-        -o [OUTPUT_FILE], --output [OUTPUT_FILE]

-                              write report to filename

- diff --git a/bandit/formatters/yaml.py b/bandit/formatters/yaml.py

- new file mode 100644

- index 0000000..69aeedb

- --- /dev/null

- +++ b/bandit/formatters/yaml.py

- @@ -0,0 +1,92 @@

- +# Copyright (c) 2017 VMware, Inc.

- +#

- +#  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.

- +

- +r"""

- +==============

- +YAML Formatter

- +==============

- +

- +This formatter outputs the issues in a yaml format.

- +

- +:Example:

- +

- +.. code-block:: none

- +

- +    filename,test_name,test_id,issue_severity,issue_confidence,issue_text,

- +    line_number,line_range

- +    examples/yaml_load.py,blacklist_calls,B301,MEDIUM,HIGH,"Use of unsafe yaml

- +    load. Allows instantiation of arbitrary objects. Consider yaml.safe_load().

- +    ",5,[5]

- +

- +.. versionadded:: 1.4.1

- +

- +"""

- +# Necessary for this formatter to work when imported on Python 2. Importing

- +# the standard library's yaml module conflicts with the name of this module.

- +from __future__ import absolute_import

- +

- +import datetime

- +import logging

- +import operator

- +import sys

- +

- +import yaml

- +

- +LOG = logging.getLogger(__name__)

- +

- +

- +def report(manager, fileobj, sev_level, conf_level, lines=-1):

- +    '''Prints issues in YAML format

- +

- +    :param manager: the bandit manager object

- +    :param fileobj: The output file object, which may be sys.stdout

- +    :param sev_level: Filtering severity level

- +    :param conf_level: Filtering confidence level

- +    :param lines: Number of lines to report, -1 for all

- +    '''

- +

- +    machine_output = {'results': [], 'errors': []}

- +    for (fname, reason) in manager.get_skipped():

- +        machine_output['errors'].append({'filename': fname, 'reason': reason})

- +

- +    results = manager.get_issue_list(sev_level=sev_level,

- +                                     conf_level=conf_level)

- +

- +    collector = [r.as_dict() for r in results]

- +

- +    itemgetter = operator.itemgetter

- +    if manager.agg_type == 'vuln':

- +        machine_output['results'] = sorted(collector,

- +                                           key=itemgetter('test_name'))

- +    else:

- +        machine_output['results'] = sorted(collector,

- +                                           key=itemgetter('filename'))

- +

- +    machine_output['metrics'] = manager.metrics.data

- +

- +    for result in machine_output['results']:

- +        if 'code' in result:

- +            code = result['code'].replace('\n', '\\n')

- +            result['code'] = code

- +

- +    # timezone agnostic format

- +    TS_FORMAT = "%Y-%m-%dT%H:%M:%SZ"

- +

- +    time_string = datetime.datetime.utcnow().strftime(TS_FORMAT)

- +    machine_output['generated_at'] = time_string

- +

- +    yaml.safe_dump(machine_output, fileobj, default_flow_style=False)

- +

- +    if fileobj.name != sys.stdout.name:

- +        LOG.info("YAML output written to file: %s", fileobj.name)

- diff --git a/doc/source/formatters/yaml.rst b/doc/source/formatters/yaml.rst

- new file mode 100644

- index 0000000..020feae

- --- /dev/null

- +++ b/doc/source/formatters/yaml.rst

- @@ -0,0 +1,5 @@

- +----

- +yaml

- +----

- +

- +.. automodule:: bandit.formatters.yaml

- diff --git a/doc/source/man/bandit.rst b/doc/source/man/bandit.rst

- index be0b993..04a3a43 100644

- --- a/doc/source/man/bandit.rst

- +++ b/doc/source/man/bandit.rst

- @@ -7,8 +7,8 @@ SYNOPSIS

-  

-  bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]

-              [-p PROFILE] [-t TESTS] [-s SKIPS] [-l] [-i]

- -            [-f {csv,html,json,screen,txt,xml}] [-o OUTPUT_FILE] [-v] [-d]

- -            [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

- +            [-f {csv,html,json,screen,txt,xml,yaml}] [-o OUTPUT_FILE] [-v]

- +            [-d] [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

-              [--ini INI_PATH] [--version]

-              targets [targets ...]

-  

- @@ -43,7 +43,7 @@ OPTIONS

-                          (-l for LOW, -ll for MEDIUM, -lll for HIGH)

-    -i, --confidence      report only issues of a given confidence level or

-                          higher (-i for LOW, -ii for MEDIUM, -iii for HIGH)

- -  -f {csv,html,json,screen,txt,xml}, --format {csv,html,json,screen,txt,xml}

- +  -f {csv,html,json,screen,txt,xml,yaml}, --format {csv,html,json,screen,txt,xml,yaml}

-                          specify output format

-    -o OUTPUT_FILE, --output OUTPUT_FILE

-                          write report to filename

- diff --git a/setup.cfg b/setup.cfg

- index ac21b7e..cb3aad6 100644

- --- a/setup.cfg

- +++ b/setup.cfg

- @@ -36,6 +36,7 @@ bandit.formatters =

-      xml = bandit.formatters.xml:report

-      html = bandit.formatters.html:report

-      screen = bandit.formatters.screen:report

- +    yaml = bandit.formatters.yaml:report

-  bandit.plugins =

-      # bandit/plugins/app_debug.py

-      flask_debug_true = bandit.plugins.app_debug:flask_debug_true

- diff --git a/tests/unit/formatters/test_yaml.py b/tests/unit/formatters/test_yaml.py

- new file mode 100644

- index 0000000..348066d

- --- /dev/null

- +++ b/tests/unit/formatters/test_yaml.py

- @@ -0,0 +1,96 @@

- +# Copyright (c) 2017 VMware, Inc.

- +#

- +#  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 collections

- +import tempfile

- +

- +import mock

- +import testtools

- +import yaml

- +

- +import bandit

- +from bandit.core import config

- +from bandit.core import constants

- +from bandit.core import issue

- +from bandit.core import manager

- +from bandit.core import metrics

- +from bandit.formatters import json as b_json

- +

- +

- +class JsonFormatterTests(testtools.TestCase):

- +

- +    def setUp(self):

- +        super(JsonFormatterTests, self).setUp()

- +        conf = config.BanditConfig()

- +        self.manager = manager.BanditManager(conf, 'file')

- +        (tmp_fd, self.tmp_fname) = tempfile.mkstemp()

- +        self.context = {'filename': self.tmp_fname,

- +                        'lineno': 4,

- +                        'linerange': [4]}

- +        self.check_name = 'hardcoded_bind_all_interfaces'

- +        self.issue = issue.Issue(bandit.MEDIUM, bandit.MEDIUM,

- +                                 'Possible binding to all interfaces.')

- +

- +        self.candidates = [issue.Issue(bandit.LOW, bandit.LOW, 'Candidate A',

- +                                       lineno=1),

- +                           issue.Issue(bandit.HIGH, bandit.HIGH, 'Candiate B',

- +                                       lineno=2)]

- +

- +        self.manager.out_file = self.tmp_fname

- +

- +        self.issue.fname = self.context['filename']

- +        self.issue.lineno = self.context['lineno']

- +        self.issue.linerange = self.context['linerange']

- +        self.issue.test = self.check_name

- +

- +        self.manager.results.append(self.issue)

- +        self.manager.metrics = metrics.Metrics()

- +

- +        # mock up the metrics

- +        for key in ['_totals', 'binding.py']:

- +            self.manager.metrics.data[key] = {'loc': 4, 'nosec': 2}

- +            for (criteria, default) in constants.CRITERIA:

- +                for rank in constants.RANKING:

- +                    self.manager.metrics.data[key]['{0}.{1}'.format(

- +                        criteria, rank

- +                    )] = 0

- +

- +    @mock.patch('bandit.core.manager.BanditManager.get_issue_list')

- +    def test_report(self, get_issue_list):

- +        self.manager.files_list = ['binding.py']

- +        self.manager.scores = [{'SEVERITY': [0] * len(constants.RANKING),

- +                                'CONFIDENCE': [0] * len(constants.RANKING)}]

- +

- +        get_issue_list.return_value = collections.OrderedDict(

- +            [(self.issue, self.candidates)])

- +

- +        tmp_file = open(self.tmp_fname, 'w')

- +        b_json.report(self.manager, tmp_file, self.issue.severity,

- +                      self.issue.confidence)

- +

- +        with open(self.tmp_fname) as f:

- +            data = yaml.load(f.read())

- +            self.assertIsNotNone(data['generated_at'])

- +            self.assertEqual(self.tmp_fname, data['results'][0]['filename'])

- +            self.assertEqual(self.issue.severity,

- +                             data['results'][0]['issue_severity'])

- +            self.assertEqual(self.issue.confidence,

- +                             data['results'][0]['issue_confidence'])

- +            self.assertEqual(self.issue.text, data['results'][0]['issue_text'])

- +            self.assertEqual(self.context['lineno'],

- +                             data['results'][0]['line_number'])

- +            self.assertEqual(self.context['linerange'],

- +                             data['results'][0]['line_range'])

- +            self.assertEqual(self.check_name, data['results'][0]['test_name'])

- +            self.assertIn('candidates', data['results'][0])

- -- 

- 2.13.6

- 

@@ -1,2208 +0,0 @@ 

- From ac2145ab7d52b2e7676b8cdfdafd4a3e13c5ec35 Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Thu, 2 Mar 2017 05:10:13 +0000

- Subject: [PATCH 15/43] Updated from global requirements

- 

- Change-Id: Ia0dcd4aa507f4babc64b503419bc5198ed6064eb

- ---

-  requirements.txt      | 2 +-

-  test-requirements.txt | 2 +-

-  2 files changed, 2 insertions(+), 2 deletions(-)

- 

- diff --git a/requirements.txt b/requirements.txt

- index 0030220..af36648 100644

- --- a/requirements.txt

- +++ b/requirements.txt

- @@ -4,4 +4,4 @@

-  GitPython>=1.0.1 # BSD License (3 clause)

-  PyYAML>=3.10.0 # MIT

-  six>=1.9.0 # MIT

- -stevedore>=1.17.1 # Apache-2.0

- +stevedore>=1.20.0 # Apache-2.0

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 9e613c6..9e1a700 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -3,7 +3,7 @@

-  # process, which may cause wedges in the gate later.

-  coverage>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

- -hacking<0.10,>=0.9.2

- +hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0

-  mock>=2.0 # BSD

-  python-subunit>=0.0.18 # Apache-2.0/BSD

-  testrepository>=0.0.18 # Apache-2.0/BSD

- -- 

- 2.13.6

- 

- From fc44e0e31aacc76cc9a6b95c607e6d0be9ffcb02 Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Thu, 2 Mar 2017 11:42:52 +0000

- Subject: [PATCH 16/43] Updated from global requirements

- 

- Change-Id: I85156d90b94995ee81bc75e0c78a8a1804dd7a0f

- ---

-  setup.py              | 2 +-

-  test-requirements.txt | 2 +-

-  2 files changed, 2 insertions(+), 2 deletions(-)

- 

- diff --git a/setup.py b/setup.py

- index 782bb21..566d844 100644

- --- a/setup.py

- +++ b/setup.py

- @@ -25,5 +25,5 @@ except ImportError:

-      pass

-  

-  setuptools.setup(

- -    setup_requires=['pbr>=1.8'],

- +    setup_requires=['pbr>=2.0.0'],

-      pbr=True)

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 9e1a700..f0b3542 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -3,7 +3,7 @@

-  # process, which may cause wedges in the gate later.

-  coverage>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

- -hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0

- +hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

-  mock>=2.0 # BSD

-  python-subunit>=0.0.18 # Apache-2.0/BSD

-  testrepository>=0.0.18 # Apache-2.0/BSD

- -- 

- 2.13.6

- 

- From c2af2c8f5a4f109bec98d2e0d6f2e21d45180336 Mon Sep 17 00:00:00 2001

- From: Jeremy Liu <liujiong@gohighsec.com>

- Date: Mon, 6 Mar 2017 17:41:14 +0800

- Subject: [PATCH 17/43] Enable coverage report in console output

- 

- This will output coverage rate of every module in console.

- 

- Change-Id: Iffa984bd404d7f197786029d5f50ee3b0a2e3e49

- ---

-  tox.ini | 4 +++-

-  1 file changed, 3 insertions(+), 1 deletion(-)

- 

- diff --git a/tox.ini b/tox.ini

- index 1ac373f..3d5f89d 100644

- --- a/tox.ini

- +++ b/tox.ini

- @@ -50,7 +50,9 @@ commands = bandit-baseline -r bandit -ll -ii

-  [testenv:cover]

-  deps = -r{toxinidir}/requirements.txt

-         -r{toxinidir}/test-requirements.txt

- -commands = python setup.py testr --coverage --testr-args='{posargs}'

- +commands =

- +    python setup.py testr --coverage --testr-args='{posargs}'

- +    coverage report

-  

-  [testenv:openstack_coverage]

-  deps = PyYAML>=3.1.0

- -- 

- 2.13.6

- 

- From 085c789490575c5a98154957b0bddf9061dcc765 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Thu, 9 Mar 2017 14:33:19 -0800

- Subject: [PATCH 18/43] Correct the yaml doc example to be actually yaml

- 

- The current doc for the yaml formatter shows an example of CSV

- output, not yaml.

- 

- Change-Id: I75b01cab5455559738d89b0803eb64261c445967

- ---

-  bandit/formatters/yaml.py | 44 +++++++++++++++++++++++++++++++++++++++-----

-  1 file changed, 39 insertions(+), 5 deletions(-)

- 

- diff --git a/bandit/formatters/yaml.py b/bandit/formatters/yaml.py

- index 69aeedb..2f26b20 100644

- --- a/bandit/formatters/yaml.py

- +++ b/bandit/formatters/yaml.py

- @@ -23,11 +23,45 @@ This formatter outputs the issues in a yaml format.

-  

-  .. code-block:: none

-  

- -    filename,test_name,test_id,issue_severity,issue_confidence,issue_text,

- -    line_number,line_range

- -    examples/yaml_load.py,blacklist_calls,B301,MEDIUM,HIGH,"Use of unsafe yaml

- -    load. Allows instantiation of arbitrary objects. Consider yaml.safe_load().

- -    ",5,[5]

- +    errors: []

- +    generated_at: '2017-03-09T22:29:30Z'

- +    metrics:

- +      _totals:

- +        CONFIDENCE.HIGH: 1

- +        CONFIDENCE.LOW: 0

- +        CONFIDENCE.MEDIUM: 0

- +        CONFIDENCE.UNDEFINED: 0

- +        SEVERITY.HIGH: 0

- +        SEVERITY.LOW: 0

- +        SEVERITY.MEDIUM: 1

- +        SEVERITY.UNDEFINED: 0

- +        loc: 9

- +        nosec: 0

- +      examples/yaml_load.py:

- +        CONFIDENCE.HIGH: 1

- +        CONFIDENCE.LOW: 0

- +        CONFIDENCE.MEDIUM: 0

- +        CONFIDENCE.UNDEFINED: 0

- +        SEVERITY.HIGH: 0

- +        SEVERITY.LOW: 0

- +        SEVERITY.MEDIUM: 1

- +        SEVERITY.UNDEFINED: 0

- +        loc: 9

- +        nosec: 0

- +    results:

- +    - code: '5     ystr = yaml.dump({''a'' : 1, ''b'' : 2, ''c'' : 3})\n

- +             6     y = yaml.load(ystr)\n7     yaml.dump(y)\n'

- +      filename: examples/yaml_load.py

- +      issue_confidence: HIGH

- +      issue_severity: MEDIUM

- +      issue_text: Use of unsafe yaml load. Allows instantiation of arbitrary

- +                  objects.

- +        Consider yaml.safe_load().

- +      line_number: 6

- +      line_range:

- +      - 6

- +      test_id: B506

- +      test_name: yaml_load

-  

-  .. versionadded:: 1.4.1

-  

- -- 

- 2.13.6

- 

- From e40af23ff67fc89f024c5a73f93c8d9a0b43caa3 Mon Sep 17 00:00:00 2001

- From: Eric Brown <browne@vmware.com>

- Date: Mon, 20 Feb 2017 12:06:19 -0800

- Subject: [PATCH 19/43] Blacklist call of ssl._create_unverified_context

- 

- The ssl._create_unverified_context creates a context for use with

- such classes as HTTPSConnection which will do no certificate or

- hostname verification. This should be flagged.

- 

- Change-Id: I326316e20ee11034c0a794f41c1bd8ae75720142

- ---

-  README.rst                          |  1 +

-  bandit/blacklists/calls.py          | 23 +++++++++++++++++++++++

-  examples/unverified_context.py      |  7 +++++++

-  tests/functional/test_functional.py |  8 ++++++++

-  4 files changed, 39 insertions(+)

-  create mode 100644 examples/unverified_context.py

- 

- diff --git a/README.rst b/README.rst

- index b7f4ba9..d3e4ba0 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -173,6 +173,7 @@ Usage::

-        B320  xml_bad_etree

-        B321  ftplib

-        B322  input

- +      B323  unverified_context

-        B401  import_telnetlib

-        B402  import_ftplib

-        B403  import_pickle

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 47858ca..075bdce 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -278,6 +278,20 @@ is safe in Python 3.

-  | B322 | input               | - input                            | High      |

-  +------+---------------------+------------------------------------+-----------+

-  

- +B323: unverified_context

- +------------------------

- +

- +By default, Python will create a secure, verified ssl context for use in such

- +classes as HTTPSConnection. However, it still allows using an insecure

- +context via the _create_unverified_context that reverts to the previous

- +behavior that does not validate certificates or perform hostname checks.

- +

- ++------+---------------------+------------------------------------+-----------+

- +| ID   |  Name               |  Calls                             |  Severity |

- ++======+=====================+====================================+===========+

- +| B322 | unverified_context  | - ssl._create_unverified_context   | Medium    |

- ++------+---------------------+------------------------------------+-----------+

- +

-  """

-  

-  from bandit.blacklists import utils

- @@ -509,4 +523,13 @@ def gen_blacklist():

-          'HIGH'

-          ))

-  

- +    sets.append(utils.build_conf_dict(

- +        'unverified_context', 'B323', ['ssl._create_unverified_context'],

- +        'By default, Python will create a secure, verified ssl context for '

- +        'use in such classes as HTTPSConnection. However, it still allows '

- +        'using an insecure context via the _create_unverified_context that '

- +        'reverts to the previous behavior that does not validate certificates '

- +        'or perform hostname checks.'

- +        ))

- +

-      return {'Call': sets}

- diff --git a/examples/unverified_context.py b/examples/unverified_context.py

- new file mode 100644

- index 0000000..0f45439

- --- /dev/null

- +++ b/examples/unverified_context.py

- @@ -0,0 +1,7 @@

- +import ssl

- +

- +# Correct

- +context = ssl.create_default_context()

- +

- +# Incorrect: unverified context

- +context = ssl._create_unverified_context()

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 5667001..4522481 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -689,3 +689,11 @@ class FunctionalTests(testtools.TestCase):

-              'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

-          }

-          self.check_example('input.py', expect)

- +

- +    def test_unverified_context(self):

- +        '''Test for `ssl._create_unverified_context`.'''

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

- +        }

- +        self.check_example('unverified_context.py', expect)

- -- 

- 2.13.6

- 

- From 693f57faaecbaeab338e173adbecc8fd566fcc79 Mon Sep 17 00:00:00 2001

- From: M V P Nitesh <m.nitesh@nectechnologies.in>

- Date: Tue, 4 Apr 2017 15:31:33 +0530

- Subject: [PATCH 20/43] Replace six.iteritems() with .items()

- 

- 1.As mentioned in [1], we should avoid using six.iteritems to achieve

- iterators. We can use dict.items instead, as it will return iterators

- in PY3 as well. And dict.items/keys will more readable.

- 2.In py2, the performance about list should be negligible, see the

- link [2].

- [1] https://wiki.openstack.org/wiki/Python3

- [2] http://lists.openstack.org/pipermail/openstack-dev/2015-June/066391.html

- 

- Change-Id: I5340fa3d71b6fba76e8fcf75f9f30432329023d2

- ---

-  bandit/cli/config_generator.py    | 5 ++---

-  bandit/cli/main.py                | 5 ++---

-  bandit/core/config.py             | 9 ++++-----

-  bandit/core/test_set.py           | 5 ++---

-  tests/unit/formatters/test_xml.py | 7 +++----

-  5 files changed, 13 insertions(+), 18 deletions(-)

- 

- diff --git a/bandit/cli/config_generator.py b/bandit/cli/config_generator.py

- index a48c518..5d532d0 100644

- --- a/bandit/cli/config_generator.py

- +++ b/bandit/cli/config_generator.py

- @@ -19,7 +19,6 @@ import logging

-  import os

-  import sys

-  

- -import six

-  import yaml

-  

-  from bandit.core import extension_loader

- @@ -158,8 +157,8 @@ def main():

-                  test_list = [tpl.format(t.plugin._test_id, t.name)

-                               for t in extension_loader.MANAGER.plugins]

-  

- -                others = [tpl.format(k, v['name']) for k, v in six.iteritems(

- -                    extension_loader.MANAGER.blacklist_by_id)]

- +                others = [tpl.format(k, v['name']) for k, v in (

- +                    extension_loader.MANAGER.blacklist_by_id.items())]

-                  test_list.extend(others)

-                  test_list.sort()

-  

- diff --git a/bandit/cli/main.py b/bandit/cli/main.py

- index 8bb61c1..423e95c 100644

- --- a/bandit/cli/main.py

- +++ b/bandit/cli/main.py

- @@ -19,7 +19,6 @@ import logging

-  import os

-  import sys

-  

- -import six

-  

-  import bandit

-  from bandit.core import config as b_config

- @@ -247,9 +246,9 @@ def main():

-      parser.set_defaults(ignore_nosec=False)

-  

-      plugin_info = ["%s\t%s" % (a[0], a[1].name) for a in

- -                   six.iteritems(extension_mgr.plugins_by_id)]

- +                   extension_mgr.plugins_by_id.items()]

-      blacklist_info = []

- -    for a in six.iteritems(extension_mgr.blacklist):

- +    for a in extension_mgr.blacklist.items():

-          for b in a[1]:

-              blacklist_info.append('%s\t%s' % (b['id'], b['name']))

-  

- diff --git a/bandit/core/config.py b/bandit/core/config.py

- index c148933..acde78a 100644

- --- a/bandit/core/config.py

- +++ b/bandit/core/config.py

- @@ -16,7 +16,6 @@

-  

-  import logging

-  

- -import six

-  import yaml

-  

-  from bandit.core import constants

- @@ -132,7 +131,7 @@ class BanditConfig(object):

-          extman = extension_loader.MANAGER

-  

-          updated_profiles = {}

- -        for name, profile in six.iteritems(self.get_option('profiles') or {}):

- +        for name, profile in (self.get_option('profiles') or {}).items():

-              # NOTE(tkelsey): can't use default of get() because value is

-              # sometimes explicity 'None', for example when the list if given in

-              # yaml but not populated with any values.

- @@ -151,7 +150,7 @@ class BanditConfig(object):

-          bad_calls = self.get_option('blacklist_calls') or {}

-          bad_calls = bad_calls.get('bad_name_sets', {})

-          for item in bad_calls:

- -            for key, val in six.iteritems(item):

- +            for key, val in item.items():

-                  val['name'] = key

-                  val['message'] = val['message'].replace('{func}', '{name}')

-                  bad_calls_list.append(val)

- @@ -159,7 +158,7 @@ class BanditConfig(object):

-          bad_imports = self.get_option('blacklist_imports') or {}

-          bad_imports = bad_imports.get('bad_import_sets', {})

-          for item in bad_imports:

- -            for key, val in six.iteritems(item):

- +            for key, val in item.items():

-                  val['name'] = key

-                  val['message'] = val['message'].replace('{module}', '{name}')

-                  val['qualnames'] = val['imports']

- @@ -179,7 +178,7 @@ class BanditConfig(object):

-                  data.remove(name)

-                  data.add('B001')

-  

- -        for name, profile in six.iteritems(profiles):

- +        for name, profile in profiles.items():

-              blacklist = {}

-              include = profile['include']

-              exclude = profile['exclude']

- diff --git a/bandit/core/test_set.py b/bandit/core/test_set.py

- index 2429aeb..b2213e8 100644

- --- a/bandit/core/test_set.py

- +++ b/bandit/core/test_set.py

- @@ -18,7 +18,6 @@

-  import importlib

-  import logging

-  

- -import six

-  

-  from bandit.core import blacklisting

-  from bandit.core import extension_loader

- @@ -46,7 +45,7 @@ class BanditTestSet(object):

-          exc = set(profile.get('exclude', []))

-  

-          all_blacklist_tests = set()

- -        for _node, tests in six.iteritems(extman.blacklist):

- +        for _node, tests in extman.blacklist.items():

-              all_blacklist_tests.update(t['id'] for t in tests)

-  

-          # this block is purely for backwards compatibility, the rules are as

- @@ -83,7 +82,7 @@ class BanditTestSet(object):

-          blacklist = profile.get('blacklist')

-          if not blacklist:  # not overridden by legacy data

-              blacklist = {}

- -            for node, tests in six.iteritems(extman.blacklist):

- +            for node, tests in extman.blacklist.items():

-                  values = [t for t in tests if t['id'] in filtering]

-                  if values:

-                      blacklist[node] = values

- diff --git a/tests/unit/formatters/test_xml.py b/tests/unit/formatters/test_xml.py

- index a16319c..39ed009 100644

- --- a/tests/unit/formatters/test_xml.py

- +++ b/tests/unit/formatters/test_xml.py

- @@ -16,7 +16,6 @@ import collections

-  import tempfile

-  from xml.etree import cElementTree as ET

-  

- -import six

-  import testtools

-  

-  import bandit

- @@ -54,12 +53,12 @@ class XmlFormatterTests(testtools.TestCase):

-          if children:

-              dd = collections.defaultdict(list)

-              for dc in map(self._xml_to_dict, children):

- -                for k, v in six.iteritems(dc):

- +                for k, v in dc.items():

-                      dd[k].append(v)

-              d = {t.tag: {k: v[0] if len(v) == 1 else v

- -                         for k, v in six.iteritems(dd)}}

- +                         for k, v in dd.items()}}

-          if t.attrib:

- -            d[t.tag].update(('@' + k, v) for k, v in six.iteritems(t.attrib))

- +            d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())

-          if t.text:

-              text = t.text.strip()

-              if children or t.attrib:

- -- 

- 2.13.6

- 

- From 88a7f256d1680ac57984a218be108ebc8a6dbab0 Mon Sep 17 00:00:00 2001

- From: loooosy <syluo5695@fiberhome.com>

- Date: Sun, 9 Apr 2017 18:00:18 +0800

- Subject: [PATCH 21/43] Optimize the link address

- 

- Use https instead of http to ensure the safety

- 

- Change-Id: I4df36b1f0a2b22fd7c9971b973cf1470400f8a4d

- ---

-  README.rst | 8 ++++----

-  1 file changed, 4 insertions(+), 4 deletions(-)

- 

- diff --git a/README.rst b/README.rst

- index d3e4ba0..41aede1 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -1,8 +1,8 @@

-  Bandit

-  ======

-  

- -.. image:: http://governance.openstack.org/badges/bandit.svg

- -    :target: http://governance.openstack.org/reference/tags/index.html

- +.. image:: https://governance.openstack.org/badges/bandit.svg

- +    :target: https://governance.openstack.org/reference/tags/index.html

-      :alt: Bandit team and repository tags

-  

-  .. image:: https://img.shields.io/pypi/v/bandit.svg

- @@ -388,8 +388,8 @@ Bandit wiki: https://wiki.openstack.org/wiki/Security/Projects/Bandit

-  Python AST module documentation: https://docs.python.org/2/library/ast.html

-  

-  Green Tree Snakes - the missing Python AST docs:

- -http://greentreesnakes.readthedocs.org/en/latest/

- +https://greentreesnakes.readthedocs.org/en/latest/

-  

-  Documentation of the various types of AST nodes that Bandit currently covers

-  or could be extended to cover:

- -http://greentreesnakes.readthedocs.org/en/latest/nodes.html

- +https://greentreesnakes.readthedocs.org/en/latest/nodes.html

- -- 

- 2.13.6

- 

- From 28d5607630622b4085f44e3b9802d8960a48499c Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Mon, 15 May 2017 00:41:53 +0000

- Subject: [PATCH 22/43] Updated from global requirements

- 

- Change-Id: I9c87d81fcd2a3612121b693051f2b2eb4f7d2384

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index f0b3542..a1f94ef 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -1,7 +1,7 @@

-  # The order of packages is significant, because pip processes them in the order

-  # of appearance. Changing the order has an impact on the overall integration

-  # process, which may cause wedges in the gate later.

- -coverage>=4.0 # Apache-2.0

- +coverage!=4.4,>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

-  hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

-  mock>=2.0 # BSD

- -- 

- 2.13.6

- 

- From 8783d47cb100cecc5ad634201d4aace40b16425b Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Wed, 17 May 2017 03:46:04 +0000

- Subject: [PATCH 23/43] Updated from global requirements

- 

- Change-Id: I9b953a312a525ac693092e2e6a02f00eec64db4d

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index a1f94ef..e87060b 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -11,7 +11,7 @@ testscenarios>=0.4 # Apache-2.0/BSD

-  testtools>=1.4.0 # MIT

-  oslotest>=1.10.0 # Apache-2.0

-  

- -sphinx>=1.5.1 # BSD

- +sphinx!=1.6.1,>=1.5.1 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

-  beautifulsoup4 # MIT

-  reno>=1.8.0 # Apache-2.0

- -- 

- 2.13.6

- 

- From 02f52a49641eeaa75bd63ae05e179f72dce2d73b Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Fri, 2 Jun 2017 21:53:29 +0000

- Subject: [PATCH 24/43] Updated from global requirements

- 

- Change-Id: I670c906f634f38b121c9708e85fd6dccb451f484

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index e87060b..ffb532d 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -14,6 +14,6 @@ oslotest>=1.10.0 # Apache-2.0

-  sphinx!=1.6.1,>=1.5.1 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

-  beautifulsoup4 # MIT

- -reno>=1.8.0 # Apache-2.0

- +reno!=2.3.1,>=1.8.0 # Apache-2.0

-  

-  pylint==1.4.5 # GPLv2

- -- 

- 2.13.6

- 

- From f10fd4f5d45a2349071cc3415d12bb60e5d5dd6c Mon Sep 17 00:00:00 2001

- From: lioplhp <hpliu5898@fiberhome.com>

- Date: Fri, 23 Jun 2017 15:45:02 +0800

- Subject: [PATCH 25/43] Enable some off-by-default checks

- 

- Some of the available checks are diskabled by default, like:

- [H106] Don't put vim configuration in source files;

- [H203] Use assertIs(Not)None to check for None.

- 

- Change-Id: Ib822b3b4cb9ae1176a8d69bbc0ab45126adc1bab

- ---

-  tox.ini | 3 +++

-  1 file changed, 3 insertions(+)

- 

- diff --git a/tox.ini b/tox.ini

- index 3d5f89d..780c7d4 100644

- --- a/tox.ini

- +++ b/tox.ini

- @@ -69,8 +69,11 @@ commands=

-      python setup.py build_sphinx

-  

-  [flake8]

- +# [H106] Don't put vim configuration in source files.

- +# [H203] Use assertIs(Not)None to check for None.

-  show-source = True

-  exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,releasenotes

- +enable-extensions = H106,H203

-  

-  [testenv:releasenotes]

-  commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html

- -- 

- 2.13.6

- 

- From d59d37d51f495ba0909b6895e531c78719d9c45d Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Tue, 27 Jun 2017 12:08:06 +0000

- Subject: [PATCH 26/43] Updated from global requirements

- 

- Change-Id: Ief6d4ed8ca25eb201de73df4c5ccdc67ffdffa0c

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index ffb532d..1b7e3f0 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -11,7 +11,7 @@ testscenarios>=0.4 # Apache-2.0/BSD

-  testtools>=1.4.0 # MIT

-  oslotest>=1.10.0 # Apache-2.0

-  

- -sphinx!=1.6.1,>=1.5.1 # BSD

- +sphinx>=1.6.2 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

-  beautifulsoup4 # MIT

-  reno!=2.3.1,>=1.8.0 # Apache-2.0

- -- 

- 2.13.6

- 

- From 715f2fd5370b45e69563b758ebb8194a85d0926a Mon Sep 17 00:00:00 2001

- From: lioplhp <hpliu5898@fiberhome.com>

- Date: Fri, 7 Jul 2017 16:37:52 +0800

- Subject: [PATCH 27/43] Add Apache License Content in index.rst

- 

- Add Apache License 2.0 Content which is necessary

- for ./releasenotes/source/index.rst.

- 

- Change-Id: I93055a0e9d2a39c8b70ed020c5c772137db38055

- ---

-  releasenotes/source/index.rst | 13 +++++++++++++

-  1 file changed, 13 insertions(+)

- 

- diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst

- index b1cf4ff..7b443aa 100644

- --- a/releasenotes/source/index.rst

- +++ b/releasenotes/source/index.rst

- @@ -1,3 +1,16 @@

- +..

- +      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

- +

- +          https://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.

- +

-  ====================

-  Bandit Release Notes

-  ====================

- -- 

- 2.13.6

- 

- From d46ac805efc13835f64343060696f23431cce0a2 Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Fri, 14 Jul 2017 04:56:23 +0000

- Subject: [PATCH 28/43] Updated from global requirements

- 

- Change-Id: I7f9863699b97514957152cf727b5af74399dc701

- ---

-  test-requirements.txt | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 1b7e3f0..7a4378b 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -13,7 +13,7 @@ oslotest>=1.10.0 # Apache-2.0

-  

-  sphinx>=1.6.2 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

- -beautifulsoup4 # MIT

- +beautifulsoup4>=4.6.0 # MIT

-  reno!=2.3.1,>=1.8.0 # Apache-2.0

-  

-  pylint==1.4.5 # GPLv2

- -- 

- 2.13.6

- 

- From 2455f9564046f3fb93e45c4704528d4836879a00 Mon Sep 17 00:00:00 2001

- From: sudhir_agarwal <sudhir.agarwal@nectechnologies.in>

- Date: Fri, 14 Jul 2017 11:00:31 +0530

- Subject: [PATCH 29/43] Fixed order of arguments in assertEqual

- 

- Some tests used incorrect order of arguments in

- assertEqual(observed, expected). The correct order expected

- by testtool is assertEqual(expected, observed).

- 

- Change-Id: I64138c2b08c44a970e7fdd96a634e8a0acd2bfa4

- ---

-  tests/unit/core/test_manager.py  | 32 ++++++++++++------------

-  tests/unit/core/test_test_set.py | 54 ++++++++++++++++++++--------------------

-  2 files changed, 43 insertions(+), 43 deletions(-)

- 

- diff --git a/tests/unit/core/test_manager.py b/tests/unit/core/test_manager.py

- index 4097194..161b55c 100644

- --- a/tests/unit/core/test_manager.py

- +++ b/tests/unit/core/test_manager.py

- @@ -51,9 +51,9 @@ class ManagerTests(testtools.TestCase):

-  

-      def test_create_manager(self):

-          # make sure we can create a manager

- -        self.assertEqual(self.manager.debug, False)

- -        self.assertEqual(self.manager.verbose, False)

- -        self.assertEqual(self.manager.agg_type, 'file')

- +        self.assertEqual(False, self.manager.debug)

- +        self.assertEqual(False, self.manager.verbose)

- +        self.assertEqual('file', self.manager.agg_type)

-  

-      def test_create_manager_with_profile(self):

-          # make sure we can create a manager

- @@ -61,9 +61,9 @@ class ManagerTests(testtools.TestCase):

-                                    debug=False, verbose=False,

-                                    profile=self.profile)

-  

- -        self.assertEqual(m.debug, False)

- -        self.assertEqual(m.verbose, False)

- -        self.assertEqual(m.agg_type, 'file')

- +        self.assertEqual(False, m.debug)

- +        self.assertEqual(False, m.verbose)

- +        self.assertEqual('file', m.agg_type)

-  

-      def test_matches_globlist(self):

-          self.assertTrue(manager._matches_glob_list('test', ['*tes*']))

- @@ -101,8 +101,8 @@ class ManagerTests(testtools.TestCase):

-                                                 included_globs=['*.py'],

-                                                 excluded_path_strings=None)

-  

- -        self.assertEqual(exc, set(['/a/c.ww']))

- -        self.assertEqual(inc, set(['/a/a.py', '/a/b.py']))

- +        self.assertEqual(set(['/a/c.ww']), exc)

- +        self.assertEqual(set(['/a/a.py', '/a/b.py']), inc)

-  

-      def test_populate_baseline_success(self):

-          # Test populate_baseline with valid JSON

- @@ -183,8 +183,8 @@ class ManagerTests(testtools.TestCase):

-      def test_discover_files_recurse_skip(self, isdir):

-          isdir.return_value = True

-          self.manager.discover_files(['thing'], False)

- -        self.assertEqual(self.manager.files_list, [])

- -        self.assertEqual(self.manager.excluded_files, [])

- +        self.assertEqual([], self.manager.files_list)

- +        self.assertEqual([], self.manager.excluded_files)

-  

-      @mock.patch('os.path.isdir')

-      def test_discover_files_recurse_files(self, isdir):

- @@ -192,8 +192,8 @@ class ManagerTests(testtools.TestCase):

-          with mock.patch.object(manager, '_get_files_from_dir') as m:

-              m.return_value = (set(['files']), set(['excluded']))

-              self.manager.discover_files(['thing'], True)

- -            self.assertEqual(self.manager.files_list, ['files'])

- -            self.assertEqual(self.manager.excluded_files, ['excluded'])

- +            self.assertEqual(['files'], self.manager.files_list)

- +            self.assertEqual(['excluded'], self.manager.excluded_files)

-  

-      @mock.patch('os.path.isdir')

-      def test_discover_files_exclude(self, isdir):

- @@ -201,8 +201,8 @@ class ManagerTests(testtools.TestCase):

-          with mock.patch.object(manager, '_is_file_included') as m:

-              m.return_value = False

-              self.manager.discover_files(['thing'], True)

- -            self.assertEqual(self.manager.files_list, [])

- -            self.assertEqual(self.manager.excluded_files, ['thing'])

- +            self.assertEqual([], self.manager.files_list)

- +            self.assertEqual(['thing'], self.manager.excluded_files)

-  

-      @mock.patch('os.path.isdir')

-      def test_discover_files_exclude_cmdline(self, isdir):

- @@ -219,8 +219,8 @@ class ManagerTests(testtools.TestCase):

-          with mock.patch.object(manager, '_is_file_included') as m:

-              m.return_value = True

-              self.manager.discover_files(['thing'], True)

- -            self.assertEqual(self.manager.files_list, ['thing'])

- -            self.assertEqual(self.manager.excluded_files, [])

- +            self.assertEqual(['thing'], self.manager.files_list)

- +            self.assertEqual([], self.manager.excluded_files)

-  

-      def test_run_tests_keyboardinterrupt(self):

-          # Test that bandit manager exits when there is a keyboard interrupt

- diff --git a/tests/unit/core/test_test_set.py b/tests/unit/core/test_test_set.py

- index b0001e6..a7ee712 100644

- --- a/tests/unit/core/test_test_set.py

- +++ b/tests/unit/core/test_test_set.py

- @@ -66,73 +66,73 @@ class BanditTestSetTests(testtools.TestCase):

-  

-      def test_has_defaults(self):

-          ts = test_set.BanditTestSet(self.config)

- -        self.assertEqual(len(ts.get_tests('Str')), 1)

- +        self.assertEqual(1, len(ts.get_tests('Str')))

-  

-      def test_profile_include_id(self):

-          profile = {'include': ['B000']}

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Str')), 1)

- +        self.assertEqual(1, len(ts.get_tests('Str')))

-  

-      def test_profile_exclude_id(self):

-          profile = {'exclude': ['B000']}

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Str')), 0)

- +        self.assertEqual(0, len(ts.get_tests('Str')))

-  

-      def test_profile_include_none(self):

-          profile = {'include': []}  # same as no include

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Str')), 1)

- +        self.assertEqual(1, len(ts.get_tests('Str')))

-  

-      def test_profile_exclude_none(self):

-          profile = {'exclude': []}  # same as no exclude

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Str')), 1)

- +        self.assertEqual(1, len(ts.get_tests('Str')))

-  

-      def test_profile_has_builtin_blacklist(self):

-          ts = test_set.BanditTestSet(self.config)

- -        self.assertEqual(len(ts.get_tests('Import')), 1)

- -        self.assertEqual(len(ts.get_tests('ImportFrom')), 1)

- -        self.assertEqual(len(ts.get_tests('Call')), 1)

- +        self.assertEqual(1, len(ts.get_tests('Import')))

- +        self.assertEqual(1, len(ts.get_tests('ImportFrom')))

- +        self.assertEqual(1, len(ts.get_tests('Call')))

-  

-      def test_profile_exclude_builtin_blacklist(self):

-          profile = {'exclude': ['B001']}

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Import')), 0)

- -        self.assertEqual(len(ts.get_tests('ImportFrom')), 0)

- -        self.assertEqual(len(ts.get_tests('Call')), 0)

- +        self.assertEqual(0, len(ts.get_tests('Import')))

- +        self.assertEqual(0, len(ts.get_tests('ImportFrom')))

- +        self.assertEqual(0, len(ts.get_tests('Call')))

-  

-      def test_profile_exclude_builtin_blacklist_specific(self):

-          profile = {'exclude': ['B302', 'B401']}

-          ts = test_set.BanditTestSet(self.config, profile)

- -        self.assertEqual(len(ts.get_tests('Import')), 0)

- -        self.assertEqual(len(ts.get_tests('ImportFrom')), 0)

- -        self.assertEqual(len(ts.get_tests('Call')), 0)

- +        self.assertEqual(0, len(ts.get_tests('Import')))

- +        self.assertEqual(0, len(ts.get_tests('ImportFrom')))

- +        self.assertEqual(0, len(ts.get_tests('Call')))

-  

-      def test_profile_filter_blacklist_none(self):

-          ts = test_set.BanditTestSet(self.config)

-          blacklist = ts.get_tests('Import')[0]

-  

- -        self.assertEqual(len(blacklist._config['Import']), 2)

- -        self.assertEqual(len(blacklist._config['ImportFrom']), 2)

- -        self.assertEqual(len(blacklist._config['Call']), 2)

- +        self.assertEqual(2, len(blacklist._config['Import']))

- +        self.assertEqual(2, len(blacklist._config['ImportFrom']))

- +        self.assertEqual(2, len(blacklist._config['Call']))

-  

-      def test_profile_filter_blacklist_one(self):

-          profile = {'exclude': ['B401']}

-          ts = test_set.BanditTestSet(self.config, profile)

-          blacklist = ts.get_tests('Import')[0]

-  

- -        self.assertEqual(len(blacklist._config['Import']), 1)

- -        self.assertEqual(len(blacklist._config['ImportFrom']), 1)

- -        self.assertEqual(len(blacklist._config['Call']), 1)

- +        self.assertEqual(1, len(blacklist._config['Import']))

- +        self.assertEqual(1, len(blacklist._config['ImportFrom']))

- +        self.assertEqual(1, len(blacklist._config['Call']))

-  

-      def test_profile_filter_blacklist_include(self):

-          profile = {'include': ['B001', 'B401']}

-          ts = test_set.BanditTestSet(self.config, profile)

-          blacklist = ts.get_tests('Import')[0]

-  

- -        self.assertEqual(len(blacklist._config['Import']), 1)

- -        self.assertEqual(len(blacklist._config['ImportFrom']), 1)

- -        self.assertEqual(len(blacklist._config['Call']), 1)

- +        self.assertEqual(1, len(blacklist._config['Import']))

- +        self.assertEqual(1, len(blacklist._config['ImportFrom']))

- +        self.assertEqual(1, len(blacklist._config['Call']))

-  

-      def test_profile_filter_blacklist_all(self):

-          profile = {'exclude': ['B401', 'B302']}

- @@ -140,9 +140,9 @@ class BanditTestSetTests(testtools.TestCase):

-  

-          # if there is no blacklist data for a node type then we wont add a

-          # blacklist test to it, as this would be pointless.

- -        self.assertEqual(len(ts.get_tests('Import')), 0)

- -        self.assertEqual(len(ts.get_tests('ImportFrom')), 0)

- -        self.assertEqual(len(ts.get_tests('Call')), 0)

- +        self.assertEqual(0, len(ts.get_tests('Import')))

- +        self.assertEqual(0, len(ts.get_tests('ImportFrom')))

- +        self.assertEqual(0, len(ts.get_tests('Call')))

-  

-      def test_profile_blacklist_compat(self):

-          data = [utils.build_conf_dict(

- @@ -157,4 +157,4 @@ class BanditTestSetTests(testtools.TestCase):

-  

-          self.assertNotIn('Import', blacklist._config)

-          self.assertNotIn('ImportFrom', blacklist._config)

- -        self.assertEqual(len(blacklist._config['Call']), 1)

- +        self.assertEqual(1, len(blacklist._config['Call']))

- -- 

- 2.13.6

- 

- From 8f1b50b5cce2ea241dbee334c5f58234b8656849 Mon Sep 17 00:00:00 2001

- From: Rajath Agasthya <rajathagasthya@gmail.com>

- Date: Sat, 29 Jul 2017 01:33:26 -0700

- Subject: [PATCH 30/43] Do not flag new way of escaping in jinja2 plugin

- 

- Makes escaping using select_autoescape function valid by checking

- for ast.Call instance and if func id == select_autoescape.

- 

- Example:

- 

- from jinja2 import Environment, select_autoescape

- env = Environment(autoescape=select_autoescape(['html', 'htm', 'xml']),

-                     loader=PackageLoader('mypackage'))

- 

- Change-Id: I47c6b346332a6d9f7c4c57dd45ab7636c78996a1

- Closes-Bug: #1684249

- ---

-  bandit/plugins/jinja2_templates.py  | 25 ++++++++++++++++++-------

-  examples/jinja2_templating.py       | 12 +++++++++++-

-  tests/functional/test_functional.py |  4 ++--

-  3 files changed, 31 insertions(+), 10 deletions(-)

- 

- diff --git a/bandit/plugins/jinja2_templates.py b/bandit/plugins/jinja2_templates.py

- index fc3a2bc..2adc77a 100644

- --- a/bandit/plugins/jinja2_templates.py

- +++ b/bandit/plugins/jinja2_templates.py

- @@ -47,13 +47,16 @@ false. A HIGH severity warning is generated in either of these scenarios.

-      14

-  

-      >> Issue: By default, jinja2 sets autoescape to False. Consider using

- -    autoescape=True to mitigate XSS vulnerabilities.

- +    autoescape=True or use the select_autoescape function to mitigate XSS

- +    vulnerabilities.

-         Severity: High   Confidence: High

-         Location: ./examples/jinja2_templating.py:15

-      14

-      15  Environment(loader=templateLoader,

-      16              load=templateLoader)

-      17

- +    18  Environment(autoescape=select_autoescape(['html', 'htm', 'xml']),

- +    19              loader=templateLoader)

-  

-  

-  .. seealso::

- @@ -93,13 +96,19 @@ def jinja2_autoescape_false(context):

-                              confidence=bandit.HIGH,

-                              text="Using jinja2 templates with autoescape="

-                                   "False is dangerous and can lead to XSS. "

- -                                 "Use autoescape=True to mitigate XSS "

- +                                 "Use autoescape=True or use the "

- +                                 "select_autoescape function to mitigate XSS "

-                                   "vulnerabilities."

-                          )

-                      # found autoescape

-                      if getattr(node, 'arg', None) == 'autoescape':

- -                        if (getattr(node.value, 'id', None) == 'True' or

- -                                getattr(node.value, 'value', None) is True):

- +                        value = getattr(node, 'value', None)

- +                        if (getattr(value, 'id', None) == 'True' or

- +                                getattr(value, 'value', None) is True):

- +                            return

- +                        # Check if select_autoescape function is used.

- +                        elif isinstance(value, ast.Call) and getattr(

- +                                value.func, 'id', None) == 'select_autoescape':

-                              return

-                          else:

-                              return bandit.Issue(

- @@ -107,8 +116,9 @@ def jinja2_autoescape_false(context):

-                                  confidence=bandit.MEDIUM,

-                                  text="Using jinja2 templates with autoescape="

-                                       "False is dangerous and can lead to XSS. "

- -                                     "Ensure autoescape=True to mitigate XSS "

- -                                     "vulnerabilities."

- +                                     "Ensure autoescape=True or use the "

- +                                     "select_autoescape function to mitigate "

- +                                     "XSS vulnerabilities."

-                              )

-              # We haven't found a keyword named autoescape, indicating default

-              # behavior

- @@ -116,5 +126,6 @@ def jinja2_autoescape_false(context):

-                  severity=bandit.HIGH,

-                  confidence=bandit.HIGH,

-                  text="By default, jinja2 sets autoescape to False. Consider "

- -                     "using autoescape=True to mitigate XSS vulnerabilities."

- +                     "using autoescape=True or use the select_autoescape "

- +                     "function to mitigate XSS vulnerabilities."

-              )

- diff --git a/examples/jinja2_templating.py b/examples/jinja2_templating.py

- index d79617f..d5aaa2d 100644

- --- a/examples/jinja2_templating.py

- +++ b/examples/jinja2_templating.py

- @@ -1,5 +1,5 @@

-  import jinja2

- -from jinja2 import Environment

- +from jinja2 import Environment, select_autoescape

-  templateLoader = jinja2.FileSystemLoader( searchpath="/" )

-  something = ''

-  

- @@ -14,3 +14,13 @@ Environment(loader=templateLoader,

-  

-  Environment(loader=templateLoader,

-              load=templateLoader)

- +

- +Environment(loader=templateLoader, autoescape=select_autoescape())

- +

- +Environment(loader=templateLoader,

- +            autoescape=select_autoescape(['html', 'htm', 'xml']))

- +

- +

- +def fake_func():

- +    return 'foobar'

- +Environment(loader=templateLoader, autoescape=fake_func())

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 4522481..5ea8220 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -441,8 +441,8 @@ class FunctionalTests(testtools.TestCase):

-      def test_jinja2_templating(self):

-          '''Test jinja templating for potential XSS bugs.'''

-          expect = {

- -            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4},

- -            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 3}

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 3}

-          }

-          self.check_example('jinja2_templating.py', expect)

-  

- -- 

- 2.13.6

- 

- From d54a65f0f018754a156cc4d105300629d9f3259a Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Fri, 18 Aug 2017 11:28:07 +0000

- Subject: [PATCH 31/43] Updated from global requirements

- 

- Change-Id: I9f572d41be228b523bc048cf491812016947d5b5

- ---

-  requirements.txt      | 2 +-

-  test-requirements.txt | 4 ++--

-  2 files changed, 3 insertions(+), 3 deletions(-)

- 

- diff --git a/requirements.txt b/requirements.txt

- index af36648..affa923 100644

- --- a/requirements.txt

- +++ b/requirements.txt

- @@ -2,6 +2,6 @@

-  # of appearance. Changing the order has an impact on the overall integration

-  # process, which may cause wedges in the gate later.

-  GitPython>=1.0.1 # BSD License (3 clause)

- -PyYAML>=3.10.0 # MIT

- +PyYAML>=3.10 # MIT

-  six>=1.9.0 # MIT

-  stevedore>=1.20.0 # Apache-2.0

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 7a4378b..b9a8990 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -4,7 +4,7 @@

-  coverage!=4.4,>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

-  hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

- -mock>=2.0 # BSD

- +mock>=2.0.0 # BSD

-  python-subunit>=0.0.18 # Apache-2.0/BSD

-  testrepository>=0.0.18 # Apache-2.0/BSD

-  testscenarios>=0.4 # Apache-2.0/BSD

- @@ -14,6 +14,6 @@ oslotest>=1.10.0 # Apache-2.0

-  sphinx>=1.6.2 # BSD

-  oslosphinx>=4.7.0 # Apache-2.0

-  beautifulsoup4>=4.6.0 # MIT

- -reno!=2.3.1,>=1.8.0 # Apache-2.0

- +reno>=2.5.0 # Apache-2.0

-  

-  pylint==1.4.5 # GPLv2

- -- 

- 2.13.6

- 

- From 05c52da55980bda5358cc337878e27839d3fc6ba Mon Sep 17 00:00:00 2001

- From: lhinds <lhinds@redhat.com>

- Date: Thu, 24 Aug 2017 19:32:38 +0100

- Subject: [PATCH 32/43] Adds simple handler to provide failed line numbers

- 

- Change adds `as err` handler to provide line number, if config yaml

- fails to parse.

- 

- Example output

- 

- [config]  ERROR   while scanning a simple key

-   in "config.yaml", line 5, column 1

- could not find expected ':'

-   in "config.yaml", line 6, column 1

- [main]  ERROR   config.yaml : Error parsing file.

- 

- Change-Id: If764a123c0dd8871dcd98f58be48c6bf0034f1d4

- Closes-Bug: #1621552

- ---

-  bandit/core/config.py | 3 ++-

-  1 file changed, 2 insertions(+), 1 deletion(-)

- 

- diff --git a/bandit/core/config.py b/bandit/core/config.py

- index acde78a..7369f06 100644

- --- a/bandit/core/config.py

- +++ b/bandit/core/config.py

- @@ -49,7 +49,8 @@ class BanditConfig(object):

-              try:

-                  self._config = yaml.safe_load(f)

-                  self.validate(config_file)

- -            except yaml.YAMLError:

- +            except yaml.YAMLError as err:

- +                LOG.error(err)

-                  raise utils.ConfigError("Error parsing file.", config_file)

-  

-              # valid config must be a dict

- -- 

- 2.13.6

- 

- From f4800cdbac253069e0cf3d5b2c55d02b8a95bbdf Mon Sep 17 00:00:00 2001

- From: lhinds <lhinds@redhat.com>

- Date: Fri, 25 Aug 2017 15:27:47 +0100

- Subject: [PATCH 33/43] Incorrect Test ID in docstring

- 

- B223 was incorrectly referenced with B222

- 

- Change-Id: I922fcb69a04e8c3a21ff71aac0d53679b50e928f

- Signed-off-by: lhinds <lhinds@redhat.com>

- ---

-  bandit/blacklists/calls.py | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/bandit/blacklists/calls.py b/bandit/blacklists/calls.py

- index 075bdce..87eccc0 100644

- --- a/bandit/blacklists/calls.py

- +++ b/bandit/blacklists/calls.py

- @@ -289,7 +289,7 @@ behavior that does not validate certificates or perform hostname checks.

-  +------+---------------------+------------------------------------+-----------+

-  | ID   |  Name               |  Calls                             |  Severity |

-  +======+=====================+====================================+===========+

- -| B322 | unverified_context  | - ssl._create_unverified_context   | Medium    |

- +| B323 | unverified_context  | - ssl._create_unverified_context   | Medium    |

-  +------+---------------------+------------------------------------+-----------+

-  

-  """

- -- 

- 2.13.6

- 

- From 277daaf09437cce61c4c913bbe9d55ca87d738d1 Mon Sep 17 00:00:00 2001

- From: sudhir_agarwal <sudhir.agarwal@nectechnologies.in>

- Date: Mon, 17 Jul 2017 11:25:14 +0530

- Subject: [PATCH 35/43] Remove unused None from dict.get()

- 

- Since the default value is None when can't get a key from a dict,

- So there is no need to use dict.get('key', None).

- 

- Change-Id: If22a4a6dbfd010a0b9574b42c23ba19a2c54dd6d

- ---

-  bandit/core/docs_utils.py           | 4 ++--

-  tests/functional/test_functional.py | 2 +-

-  2 files changed, 3 insertions(+), 3 deletions(-)

- 

- diff --git a/bandit/core/docs_utils.py b/bandit/core/docs_utils.py

- index 8f268e0..96ab884 100644

- --- a/bandit/core/docs_utils.py

- +++ b/bandit/core/docs_utils.py

- @@ -24,11 +24,11 @@ def get_url(bid):

-      # later though.

-      from bandit.core import extension_loader

-  

- -    info = extension_loader.MANAGER.plugins_by_id.get(bid, None)

- +    info = extension_loader.MANAGER.plugins_by_id.get(bid)

-      if info is not None:

-          return BASE_URL + ('plugins/%s.html' % info.plugin.__name__)

-  

- -    info = extension_loader.MANAGER.blacklist_by_id.get(bid, None)

- +    info = extension_loader.MANAGER.blacklist_by_id.get(bid)

-      if info is not None:

-          template = 'blacklists/blacklist_{kind}.html#{id}-{name}'

-          info['name'] = info['name'].replace('_', '-')

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index 5ea8220..b13edc5 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -105,7 +105,7 @@ class FunctionalTests(testtools.TestCase):

-                  for rank in C.RANKING:

-                      label = '{0}.{1}'.format(criteria, rank)

-                      expected = 0

- -                    if expect['issues'].get(criteria, None).get(rank, None):

- +                    if expect['issues'].get(criteria).get(rank):

-                          expected = expect['issues'][criteria][rank]

-                      self.assertEqual(expected, m['_totals'][label])

-  

- -- 

- 2.13.6

- 

- From 1a3d28b44064c84fccf6d922a4f0816add0bf0f9 Mon Sep 17 00:00:00 2001

- From: shangxiaobj <shangxiaobj@inspur.com>

- Date: Wed, 13 Sep 2017 00:11:27 -0700

- Subject: [PATCH 36/43] [Trivialfix]Fix typos

- 

- Fix the typos in bandit.

- 

- Change-Id: I93db489ae27c3f4490e988d342802f3f29f9255f

- ---

-  examples/imports-function.py      | 2 +-

-  tests/functional/test_baseline.py | 2 +-

-  tests/unit/cli/test_main.py       | 2 +-

-  3 files changed, 3 insertions(+), 3 deletions(-)

- 

- diff --git a/examples/imports-function.py b/examples/imports-function.py

- index 7f9ac1d..bff8aa4 100644

- --- a/examples/imports-function.py

- +++ b/examples/imports-function.py

- @@ -7,6 +7,6 @@ subprocess = __import__("subprocess")

-  # see bug https://bugs.launchpad.net/bandit/+bug/1396333

-  __import__()

-  

- -# TODO(??): bandit can not find this one unfortunatly (no symbol tab)

- +# TODO(??): bandit can not find this one unfortunately (no symbol tab)

-  a = 'subprocess'

-  __import__(a)

- diff --git a/tests/functional/test_baseline.py b/tests/functional/test_baseline.py

- index cad7bf1..ff8fc73 100644

- --- a/tests/functional/test_baseline.py

- +++ b/tests/functional/test_baseline.py

- @@ -222,7 +222,7 @@ class BaselineFunctionalTests(testtools.TestCase):

-                                   "new_candidates-all.py"}

-          target_directory, baseline_code = (self._create_baseline(

-                                             baseline_report_files))

- -        # assert the intial baseline found results

- +        # assert the initial baseline found results

-          self.assertEqual(1, baseline_code)

-          baseline_report = os.path.join(target_directory,

-                                         self.baseline_report_file)

- diff --git a/tests/unit/cli/test_main.py b/tests/unit/cli/test_main.py

- index 7e79ca5..adc95cd 100644

- --- a/tests/unit/cli/test_main.py

- +++ b/tests/unit/cli/test_main.py

- @@ -151,7 +151,7 @@ class BanditCLIMainTests(testtools.TestCase):

-                           option_name))

-  

-      def test_log_option_source_no_values(self):

- -        # Test that None is returned when no command arguement or ini value are

- +        # Test that None is returned when no command argument or ini value are

-          # provided

-          option_name = 'aggregate'

-          self.assertIsNone(bandit._log_option_source(None, None, option_name))

- -- 

- 2.13.6

- 

- From dab37aace404db7f368084d9a97164e1f4d98fbf Mon Sep 17 00:00:00 2001

- From: zhangyangyang <zhangyangyang@unionpay.com>

- Date: Wed, 20 Sep 2017 21:44:47 +0800

- Subject: [PATCH 37/43] Cleanup test-requirements

- 

- python-subunit is not used directly anywhere

- and it is dependency of both testrepository

- and os-testr

- (probably was used by some tox wrapper script before)

- 

- Change-Id: Id2df62be0364a262ff4b0056ffb7a6b779cc2813

- ---

-  test-requirements.txt | 1 -

-  1 file changed, 1 deletion(-)

- 

- diff --git a/test-requirements.txt b/test-requirements.txt

- index b9a8990..b126073 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -5,7 +5,6 @@ coverage!=4.4,>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

-  hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

-  mock>=2.0.0 # BSD

- -python-subunit>=0.0.18 # Apache-2.0/BSD

-  testrepository>=0.0.18 # Apache-2.0/BSD

-  testscenarios>=0.4 # Apache-2.0/BSD

-  testtools>=1.4.0 # MIT

- -- 

- 2.13.6

- 

- From a98519927be935eb6f331226c1fcc272822d4a68 Mon Sep 17 00:00:00 2001

- From: Rajath Agasthya <rajathagasthya@gmail.com>

- Date: Fri, 15 Sep 2017 18:25:55 -0700

- Subject: [PATCH 38/43] Plugin to flag insecure hash functions created using

-  hashlib.new()

- 

- Currently, insecure hash function usage by calling hashlib.md5()

- is flagged in B303. But these hash functions can also be obtained using

- hashlib.new(), by passing 'md4' or 'md5' as an argument. This plugin

- checks such usage.

- 

- Change-Id: I8d368aea287e1287e5f638b48c4297d355037839

- Closes-Bug: #1708582

- ---

-  README.rst                                       |  1 +

-  bandit/plugins/hashlib_new_insecure_functions.py | 63 ++++++++++++++++++++++++

-  examples/hashlib_new_insecure_functions.py       | 16 ++++++

-  setup.cfg                                        |  3 ++

-  tests/functional/test_functional.py              |  8 +++

-  5 files changed, 91 insertions(+)

-  create mode 100644 bandit/plugins/hashlib_new_insecure_functions.py

-  create mode 100644 examples/hashlib_new_insecure_functions.py

- 

- diff --git a/README.rst b/README.rst

- index 41aede1..f53de9f 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -174,6 +174,7 @@ Usage::

-        B321  ftplib

-        B322  input

-        B323  unverified_context

- +      B324  hashlib_new_insecure_functions

-        B401  import_telnetlib

-        B402  import_ftplib

-        B403  import_pickle

- diff --git a/bandit/plugins/hashlib_new_insecure_functions.py b/bandit/plugins/hashlib_new_insecure_functions.py

- new file mode 100644

- index 0000000..46436c2

- --- /dev/null

- +++ b/bandit/plugins/hashlib_new_insecure_functions.py

- @@ -0,0 +1,63 @@

- +# -*- 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.

- +

- +r"""

- +==========================================================================

- +B324: Test for use of insecure md4 and md5 hash functions in hashlib.new()

- +==========================================================================

- +

- +This plugin checks for the usage of the insecure MD4 and MD5 hash functions

- +in ``hashlib.new`` function. The ``hashlib.new`` function provides the ability

- +to construct a new hashing object using the named algorithm. This can be used

- +to create insecure hash functions like MD4 and MD5 if they are passed as

- +algorithm names to this function.

- +

- +This is similar to B303 blacklist check, except that this checks for insecure

- +hash functions created using ``hashlib.new`` function.

- +

- +:Example:

- +

- +    >> Issue: [B324:hashlib_new] Use of insecure MD4 or MD5 hash function.

- +       Severity: Medium   Confidence: High

- +       Location: examples/hashlib_new_insecure_funcs.py:3

- +    2

- +    3  md5_hash = hashlib.new('md5', string='test')

- +    4  print(md5_hash)

- +

- +

- +.. versionadded:: 1.5.0

- +

- +"""

- +

- +import bandit

- +from bandit.core import test_properties as test

- +

- +

- +@test.test_id('B324')

- +@test.checks('Call')

- +def hashlib_new(context):

- +    if isinstance(context.call_function_name_qual, str):

- +        qualname_list = context.call_function_name_qual.split('.')

- +        func = qualname_list[-1]

- +        if 'hashlib' in qualname_list and func == 'new':

- +            args = context.call_args

- +            keywords = context.call_keywords

- +            name = args[0] if args else keywords['name']

- +            if name.lower() in ('md4', 'md5'):

- +                return bandit.Issue(

- +                    severity=bandit.MEDIUM,

- +                    confidence=bandit.HIGH,

- +                    text="Use of insecure MD4 or MD5 hash function.",

- +                    lineno=context.node.lineno,

- +                )

- diff --git a/examples/hashlib_new_insecure_functions.py b/examples/hashlib_new_insecure_functions.py

- new file mode 100644

- index 0000000..eeddcca

- --- /dev/null

- +++ b/examples/hashlib_new_insecure_functions.py

- @@ -0,0 +1,16 @@

- +import hashlib

- +

- +hashlib.new('md5')

- +

- +hashlib.new('md4', 'test')

- +

- +hashlib.new(name='md5', string='test')

- +

- +hashlib.new('MD4', string='test')

- +

- +hashlib.new(string='test', name='MD5')

- +

- +# Test that plugin does not flag valid hash functions.

- +hashlib.new('sha256')

- +

- +hashlib.new('SHA512')

- diff --git a/setup.cfg b/setup.cfg

- index cb3aad6..a8fdbbb 100644

- --- a/setup.cfg

- +++ b/setup.cfg

- @@ -81,6 +81,9 @@ bandit.plugins =

-      # bandit/plugins/injection_sql.py

-      hardcoded_sql_expressions = bandit.plugins.injection_sql:hardcoded_sql_expressions

-  

- +    # bandit/plugins/hashlib_new_insecure_functions.py

- +    hashlib_new_insecure_functions = bandit.plugins.hashlib_new_insecure_functions:hashlib_new

- +

-      # bandit/plugins/injection_wildcard.py

-      linux_commands_wildcard_injection = bandit.plugins.injection_wildcard:linux_commands_wildcard_injection

-  

- diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py

- index db6e3db..60dd585 100644

- --- a/tests/functional/test_functional.py

- +++ b/tests/functional/test_functional.py

- @@ -697,3 +697,11 @@ class FunctionalTests(testtools.TestCase):

-              'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}

-          }

-          self.check_example('unverified_context.py', expect)

- +

- +    def test_hashlib_new_insecure_functions(self):

- +        '''Test insecure hash functions created by `hashlib.new`.'''

- +        expect = {

- +            'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 5, 'HIGH': 0},

- +            'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}

- +        }

- +        self.check_example('hashlib_new_insecure_functions.py', expect)

- -- 

- 2.13.6

- 

- From d159335700938f25ebd2606c066e3895e2a3d577 Mon Sep 17 00:00:00 2001

- From: Marek Cermak <macermak@redhat.com>

- Date: Mon, 9 Oct 2017 15:57:56 +0200

- Subject: [PATCH 39/43] Custom formatter

- 

- Implements: custom formatter

- 

- Custom formatter can be used to output a machine-readable, easily

- parsable and customizable format using set of predefined tags

- to suite various needs.

- 

- Output string is formatted using python string.format() standards

- and therefore provides familiar usage.

- 

- Usage: bandit --format custom [--msg-template MSG-TEMPLATE] targets

- 

- See bandit --help for additional information and list of available tags

- 

- modified:   bandit/cli/main.py

- modified:   bandit/core/manager.py

- modified:   README.rst

- modified:   setup.cfg

- new file:   bandit/formatters/custom.py

- 

- Change-Id: I900c9689cddb048db58608c443305e05e7a4be14

- Signed-off-by: Marek Cermak <macermak@redhat.com>

- ---

-  README.rst                       |  64 ++++++++++++++-

-  bandit/cli/main.py               |  45 ++++++++++-

-  bandit/core/manager.py           |  14 +++-

-  bandit/formatters/custom.py      | 163 +++++++++++++++++++++++++++++++++++++++

-  doc/source/man/bandit.rst        |  35 ++++++++-

-  setup.cfg                        |   1 +

-  tests/functional/test_runtime.py |   2 +-

-  7 files changed, 311 insertions(+), 13 deletions(-)

-  create mode 100644 bandit/formatters/custom.py

- 

- diff --git a/README.rst b/README.rst

- index 41aede1..de3773f 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -87,8 +87,9 @@ Usage::

-      $ bandit -h

-      usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]

-                    [-p PROFILE] [-t TESTS] [-s SKIPS] [-l] [-i]

- -                  [-f {csv,html,json,screen,txt,xml,yaml}] [-o [OUTPUT_FILE]] [-v]

- -                  [-d] [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

- +                  [-f {csv,custom,html,json,screen,txt,xml,yaml}]

- +                  [--msg-template MSG_TEMPLATE] [-o [OUTPUT_FILE]] [-v] [-d]

- +                  [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

-                    [--ini INI_PATH] [--version]

-                    targets [targets ...]

-  

- @@ -118,8 +119,12 @@ Usage::

-                              (-l for LOW, -ll for MEDIUM, -lll for HIGH)

-        -i, --confidence      report only issues of a given confidence level or

-                              higher (-i for LOW, -ii for MEDIUM, -iii for HIGH)

- -      -f {csv,html,json,screen,txt,xml,yaml}, --format {csv,html,json,screen,txt,xml,yaml}

- +      -f {csv,custom,html,json,screen,txt,xml,yaml}, --format {csv,custom,html,json,screen,txt,xml,yaml}

-                              specify output format

- +      --msg-template        MSG_TEMPLATE

- +                            specify output message template (only usable with

- +                            --format custom), see CUSTOM FORMAT section for list

- +                            of available values

-        -o [OUTPUT_FILE], --output [OUTPUT_FILE]

-                              write report to filename

-        -v, --verbose         output extra information like excluded and included

- @@ -137,7 +142,33 @@ Usage::

-                              arguments

-        --version             show program's version number and exit

-  

- +    CUSTOM FORMATTING

- +    -----------------

- +

- +    Available tags:

- +

- +        {abspath}, {relpath}, {line},  {test_id},

- +        {severity}, {msg}, {confidence}, {range}

- +

- +    Example usage:

- +

- +        Default template:

- +        bandit -r examples/ --format custom --msg-template \

- +        "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- +

- +        Provides same output as:

- +        bandit -r examples/ --format custom

- +

- +        Tags can also be formatted in python string.format() style:

- +        bandit -r examples/ --format custom --msg-template \

- +        "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"

- +

- +        See python documentation for more information about formatting style:

- +        https://docs.python.org/3.4/library/string.html

- +

-      The following tests were discovered and loaded:

- +    -----------------------------------------------

- +

-        B101  assert_used

-        B102  exec_used

-        B103  set_bad_file_permissions

- @@ -339,6 +370,33 @@ To register your plugin, you have two options:

-          bandit.plugins =

-              mako = bandit_mako

-  

- +

- +Custom Formatting

- +-----------------

- +

- +Available tags:

- +

- +::

- +    {abspath}, {relpath}, {line},  {test_id},

- +    {severity}, {msg}, {confidence}, {range}

- +

- +Example usage:

- +

- +  Default template::

- +    bandit -r examples/ --format custom --msg-template \

- +    "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- +

- +  Provides same output as::

- +    bandit -r examples/ --format custom

- +

- +  Tags can also be formatted in python string.format() style::

- +    bandit -r examples/ --format custom --msg-template \

- +    "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"

- +

- +See python documentation for more information about formatting style:

- +https://docs.python.org/3.4/library/string.html

- +

- +

-  Contributing

-  ------------

-  Contributions to Bandit are always welcome! We can be found on

- diff --git a/bandit/cli/main.py b/bandit/cli/main.py

- index 423e95c..2c4a403 100644

- --- a/bandit/cli/main.py

- +++ b/bandit/cli/main.py

- @@ -18,6 +18,7 @@ import fnmatch

-  import logging

-  import os

-  import sys

- +import textwrap

-  

-  

-  import bandit

- @@ -206,6 +207,13 @@ def main():

-          choices=sorted(extension_mgr.formatter_names)

-      )

-      parser.add_argument(

- +        '--msg-template', action='store',

- +        default=None, help='specify output message template'

- +                           ' (only usable with --format custom),'

- +                           ' see CUSTOM FORMAT section'

- +                           ' for list of available values',

- +    )

- +    parser.add_argument(

-          '-o', '--output', dest='output_file', action='store', nargs='?',

-          type=argparse.FileType('w'), default=sys.stdout,

-          help='write report to filename'

- @@ -253,11 +261,41 @@ def main():

-              blacklist_info.append('%s\t%s' % (b['id'], b['name']))

-  

-      plugin_list = '\n\t'.join(sorted(set(plugin_info + blacklist_info)))

- -    parser.epilog = ('The following tests were discovered and'

- -                     ' loaded:\n\t{0}\n'.format(plugin_list))

- +    dedent_text = textwrap.dedent('''

- +    CUSTOM FORMATTING

- +    -----------------

- +

- +    Available tags:

- +

- +        {abspath}, {relpath}, {line},  {test_id},

- +        {severity}, {msg}, {confidence}, {range}

- +

- +    Example usage:

- +

- +        Default template:

- +        bandit -r examples/ --format custom --msg-template \\

- +        "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- +

- +        Provides same output as:

- +        bandit -r examples/ --format custom

- +

- +        Tags can also be formatted in python string.format() style:

- +        bandit -r examples/ --format custom --msg-template \\

- +        "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"

- +

- +        See python documentation for more information about formatting style:

- +        https://docs.python.org/3.4/library/string.html

- +

- +    The following tests were discovered and loaded:

- +    -----------------------------------------------

- +    ''')

- +    parser.epilog = dedent_text + "\t{0}".format(plugin_list)

-  

-      # setup work - parse arguments, and initialize BanditManager

-      args = parser.parse_args()

- +    # Check if `--msg-template` is not present without custom formatter

- +    if args.output_format != 'custom' and args.msg_template is not None:

- +        parser.error("--msg-template can only be used with --format=custom")

-  

-      try:

-          b_conf = b_config.BanditConfig(config_file=args.config_file)

- @@ -341,7 +379,8 @@ def main():

-                           sev_level,

-                           conf_level,

-                           args.output_file,

- -                         args.output_format)

- +                         args.output_format,

- +                         args.msg_template)

-  

-      # return an exit code of 1 if there are results, 0 otherwise

-      if b_mgr.results_count(sev_filter=sev_level, conf_filter=conf_level) > 0:

- diff --git a/bandit/core/manager.py b/bandit/core/manager.py

- index d4febce..cb8b574 100644

- --- a/bandit/core/manager.py

- +++ b/bandit/core/manager.py

- @@ -136,7 +136,7 @@ class BanditManager(object):

-          return len(self.get_issue_list(sev_filter, conf_filter))

-  

-      def output_results(self, lines, sev_level, conf_level, output_file,

- -                       output_format):

- +                       output_format, template=None):

-          '''Outputs results from the result store

-  

-          :param lines: How many surrounding lines to show per result

- @@ -144,6 +144,9 @@ class BanditManager(object):

-          :param conf_level: Which confidence levels to show (LOW, MEDIUM, HIGH)

-          :param output_file: File to store results

-          :param output_format: output format plugin name

- +        :param template: Output template with non-terminal tags <N>

- +                         (default:  {abspath}:{line}:

- +                         {test_id}[bandit]: {severity}: {msg})

-          :return: -

-          '''

-          try:

- @@ -153,8 +156,13 @@ class BanditManager(object):

-  

-              formatter = formatters_mgr[output_format]

-              report_func = formatter.plugin

- -            report_func(self, fileobj=output_file, sev_level=sev_level,

- -                        conf_level=conf_level, lines=lines)

- +            if output_format == 'custom':

- +                report_func(self, fileobj=output_file, sev_level=sev_level,

- +                            conf_level=conf_level, lines=lines,

- +                            template=template)

- +            else:

- +                report_func(self, fileobj=output_file, sev_level=sev_level,

- +                            conf_level=conf_level, lines=lines)

-  

-          except Exception as e:

-              raise RuntimeError("Unable to output report using '%s' formatter: "

- diff --git a/bandit/formatters/custom.py b/bandit/formatters/custom.py

- new file mode 100644

- index 0000000..864ff4f

- --- /dev/null

- +++ b/bandit/formatters/custom.py

- @@ -0,0 +1,163 @@

- +# Copyright (c) 2017 Hewlett Packard Enterprise

- +# -*- 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.

- +

- +r"""

- +================

- +Custom Formatter

- +================

- +

- +This formatter outputs the issues in custom machine-readable format.

- +

- +default template: {abspath}:{line}: {test_id}[bandit]: {severity}: {msg}

- +

- +:Example:

- +

- +/usr/lib/python3.6/site-packages/openlp/core/utils/__init__.py: \

- +405: B310[bandit]: MEDIUM: Audit url open for permitted schemes. \

- +Allowing use of file:/ or custom schemes is often unexpected.

- +

- +"""

- +

- +import logging

- +import os

- +import re

- +import string

- +import sys

- +

- +from bandit.core import test_properties

- +

- +

- +LOG = logging.getLogger(__name__)

- +

- +

- +class SafeMapper(dict):

- +    """Safe mapper to handle format key errors"""

- +    @classmethod  # To prevent PEP8 warnings in the test suite

- +    def __missing__(cls, key):

- +        return "{%s}" % key

- +

- +

- +@test_properties.accepts_baseline

- +def report(manager, fileobj, sev_level, conf_level, lines=-1, template=None):

- +    """Prints issues in custom format

- +

- +    :param manager: the bandit manager object

- +    :param fileobj: The output file object, which may be sys.stdout

- +    :param sev_level: Filtering severity level

- +    :param conf_level: Filtering confidence level

- +    :param lines: Number of lines to report, -1 for all

- +    :param template: Output template with non-terminal tags <N>

- +                    (default: '{abspath}:{line}:

- +                    {test_id}[bandit]: {severity}: {msg}')

- +    """

- +

- +    machine_output = {'results': [], 'errors': []}

- +    for (fname, reason) in manager.get_skipped():

- +        machine_output['errors'].append({'filename': fname,

- +                                         'reason': reason})

- +

- +    results = manager.get_issue_list(sev_level=sev_level,

- +                                     conf_level=conf_level)

- +

- +    msg_template = template

- +    if template is None:

- +        msg_template = "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- +

- +    # Dictionary of non-terminal tags that will be expanded

- +    tag_mapper = {

- +        'abspath': lambda issue: os.path.abspath(issue.fname),

- +        'relpath': lambda issue: os.path.relpath(issue.fname),

- +        'line': lambda issue: issue.lineno,

- +        'test_id': lambda issue: issue.test_id,

- +        'severity': lambda issue: issue.severity,

- +        'msg': lambda issue: issue.text,

- +        'confidence': lambda issue: issue.confidence,

- +        'range': lambda issue: issue.linerange

- +    }

- +

- +    # Create dictionary with tag sets to speed up search for similar tags

- +    tag_sim_dict = dict(

- +        [(tag, set(tag)) for tag, _ in tag_mapper.items()]

- +    )

- +

- +    # Parse the format_string template and check the validity of tags

- +    try:

- +        parsed_template_orig = list(string.Formatter().parse(msg_template))

- +        # of type (literal_text, field_name, fmt_spec, conversion)

- +

- +        # Check the format validity only, ignore keys

- +        string.Formatter().vformat(msg_template, (), SafeMapper(line=0))

- +    except ValueError as e:

- +        LOG.error("Template is not in valid format: %s", e.args[0])

- +        sys.exit(2)

- +

- +    tag_set = {t[1] for t in parsed_template_orig if t[1] is not None}

- +    if not tag_set:

- +        LOG.error("No tags were found in the template. Are you missing '{}'?")

- +        sys.exit(2)

- +

- +    def get_similar_tag(tag):

- +        similarity_list = [(len(set(tag) & t_set), t)

- +                           for t, t_set in tag_sim_dict.items()]

- +        return sorted(similarity_list)[-1][1]

- +

- +    tag_blacklist = []

- +    for tag in tag_set:

- +        # check if the tag is in dictionary

- +        if tag not in tag_mapper:

- +            similar_tag = get_similar_tag(tag)

- +            LOG.warning(

- +                "Tag '%s' was not recognized and will be skipped, "

- +                "did you mean to use '%s'?", tag, similar_tag

- +            )

- +            tag_blacklist += [tag]

- +

- +    # Compose the message template back with the valid values only

- +    msg_parsed_template_list = []

- +    for literal_text, field_name, fmt_spec, conversion in parsed_template_orig:

- +        if literal_text:

- +            # if there is '{' or '}', double it to prevent expansion

- +            literal_text = re.sub('{', '{{', literal_text)

- +            literal_text = re.sub('}', '}}', literal_text)

- +            msg_parsed_template_list.append(literal_text)

- +

- +        if field_name is not None:

- +            if field_name in tag_blacklist:

- +                msg_parsed_template_list.append(field_name)

- +                continue

- +            # Append the fmt_spec part

- +            params = [field_name, fmt_spec, conversion]

- +            markers = ['', ':', '!']

- +            msg_parsed_template_list.append(

- +                ['{'] +

- +                ["%s" % (m + p) if p else ''

- +                 for m, p in zip(markers, params)] +

- +                ['}']

- +            )

- +

- +    msg_parsed_template = "".join([item for lst in msg_parsed_template_list

- +                                   for item in lst]) + "\n"

- +    limit = lines if lines > 0 else None

- +    with fileobj:

- +        for defect in results[:limit]:

- +            evaluated_tags = SafeMapper(

- +                (k, v(defect)) for k, v in tag_mapper.items()

- +            )

- +            output = msg_parsed_template.format(**evaluated_tags)

- +

- +            fileobj.write(output)

- +

- +    if fileobj.name != sys.stdout.name:

- +        LOG.info("Result written to file: %s", fileobj.name)

- diff --git a/doc/source/man/bandit.rst b/doc/source/man/bandit.rst

- index 04a3a43..363b857 100644

- --- a/doc/source/man/bandit.rst

- +++ b/doc/source/man/bandit.rst

- @@ -7,8 +7,9 @@ SYNOPSIS

-  

-  bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]

-              [-p PROFILE] [-t TESTS] [-s SKIPS] [-l] [-i]

- -            [-f {csv,html,json,screen,txt,xml,yaml}] [-o OUTPUT_FILE] [-v]

- -            [-d] [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

- +            [-f {csv,custom,html,json,screen,txt,xml,yaml}]

- +            [--msg-template MSG_TEMPLATE] [-o OUTPUT_FILE] [-v] [-d]

- +            [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]

-              [--ini INI_PATH] [--version]

-              targets [targets ...]

-  

- @@ -43,8 +44,12 @@ OPTIONS

-                          (-l for LOW, -ll for MEDIUM, -lll for HIGH)

-    -i, --confidence      report only issues of a given confidence level or

-                          higher (-i for LOW, -ii for MEDIUM, -iii for HIGH)

- -  -f {csv,html,json,screen,txt,xml,yaml}, --format {csv,html,json,screen,txt,xml,yaml}

- +  -f {csv,custom,html,json,screen,txt,xml,yaml}, --format {csv,custom,html,json,screen,txt,xml,yaml}

-                          specify output format

- +  --msg-template MSG_TEMPLATE

- +                        specify output message template (only usable with

- +                        --format custom), see CUSTOM FORMAT section for list

- +                        of available values

-    -o OUTPUT_FILE, --output OUTPUT_FILE

-                          write report to filename

-    -v, --verbose         output extra information like excluded and included

- @@ -62,6 +67,30 @@ OPTIONS

-                          arguments

-    --version             show program's version number and exit

-  

- +CUSTOM FORMATTING

- +-----------------

- +

- +Available tags:

- +

- +    {abspath}, {relpath}, {line},  {test_id},

- +    {severity}, {msg}, {confidence}, {range}

- +

- +Example usage:

- +

- +    Default template:

- +    bandit -r examples/ --format custom --msg-template \

- +    "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- +

- +    Provides same output as:

- +    bandit -r examples/ --format custom

- +

- +    Tags can also be formatted in python string.format() style:

- +    bandit -r examples/ --format custom --msg-template \

- +    "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"

- +

- +    See python documentation for more information about formatting style:

- +    https://docs.python.org/3.4/library/string.html

- +

-  FILES

-  =====

-  

- diff --git a/setup.cfg b/setup.cfg

- index cb3aad6..78bcb8e 100644

- --- a/setup.cfg

- +++ b/setup.cfg

- @@ -37,6 +37,7 @@ bandit.formatters =

-      html = bandit.formatters.html:report

-      screen = bandit.formatters.screen:report

-      yaml = bandit.formatters.yaml:report

- +    custom = bandit.formatters.custom:report

-  bandit.plugins =

-      # bandit/plugins/app_debug.py

-      flask_debug_true = bandit.plugins.app_debug:flask_debug_true

- diff --git a/tests/functional/test_runtime.py b/tests/functional/test_runtime.py

- index 2fe8ff2..5fa1997 100644

- --- a/tests/functional/test_runtime.py

- +++ b/tests/functional/test_runtime.py

- @@ -77,7 +77,7 @@ class RuntimeTests(testtools.TestCase):

-          self.assertIn("tests were discovered and loaded:", output)

-  

-      def test_help_in_readme(self):

- -        replace_list = [' ', '\t']

- +        replace_list = [' ', '\t', '\n']

-          (retcode, output) = self._test_runtime(['bandit', '-h'])

-          for i in replace_list:

-              output = output.replace(i, '')

- -- 

- 2.13.6

- 

- From ce108f0edadcb0ff6ec11c83b93738dfc94c7654 Mon Sep 17 00:00:00 2001

- From: Gage Hugo <gagehugo@gmail.com>

- Date: Thu, 2 Nov 2017 13:49:04 -0500

- Subject: [PATCH 40/43] Migrate to stestr

- 

- This change migrates the testing suite from using ostestr and testr

- to using stester. Also cleaned up a missing space from tox.ini.

- 

- Change-Id: I886401a1efce6cb617a4db7a90ec9454bbea1d71

- ---

-  .stestr.conf          |  4 ++++

-  .testr.conf           |  7 -------

-  test-requirements.txt |  2 +-

-  tox.ini               | 15 ++++++++++-----

-  5 files changed, 16 insertions(+), 14 deletions(-)

-  create mode 100644 .stestr.conf

-  delete mode 100644 .testr.conf

- 

- diff --git a/.stestr.conf b/.stestr.conf

- new file mode 100644

- index 0000000..64fe016

- --- /dev/null

- +++ b/.stestr.conf

- @@ -0,0 +1,4 @@

- +[DEFAULT]

- +test_path=${OS_TEST_PATH:-./tests/unit}

- +top_dir=./

- +group_regex=.*(test_cert_setup)

- diff --git a/.testr.conf b/.testr.conf

- deleted file mode 100644

- index 35d9ba4..0000000

- --- a/.testr.conf

- +++ /dev/null

- @@ -1,7 +0,0 @@

- -[DEFAULT]

- -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \

- -             OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \

- -             OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \

- -             ${PYTHON:-python} -m subunit.run discover -t ./ ./tests $LISTOPT $IDOPTION

- -test_id_option=--load-list $IDFILE

- -test_list_option=--list

- diff --git a/test-requirements.txt b/test-requirements.txt

- index b126073..1fe8d4e 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -5,7 +5,7 @@ coverage!=4.4,>=4.0 # Apache-2.0

-  fixtures>=3.0.0 # Apache-2.0/BSD

-  hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

-  mock>=2.0.0 # BSD

- -testrepository>=0.0.18 # Apache-2.0/BSD

- +stestr>=1.0.0 # Apache-2.0

-  testscenarios>=0.4 # Apache-2.0/BSD

-  testtools>=1.4.0 # MIT

-  oslotest>=1.10.0 # Apache-2.0

- diff --git a/tox.ini b/tox.ini

- index 780c7d4..6f22625 100644

- --- a/tox.ini

- +++ b/tox.ini

- @@ -10,13 +10,14 @@ setenv =

-      VIRTUAL_ENV={envdir}

-      BRANCH_NAME=master

-      CLIENT_NAME=bandit

- -   VIRTUAL_ENV={envdir}

- +    VIRTUAL_ENV={envdir}

-  deps = -r{toxinidir}/requirements.txt

-         -r{toxinidir}/test-requirements.txt

-  commands =

- -          coverage erase

- -          python setup.py testr --coverage --slowest --testr-args='{posargs}'

- -          coverage report -m

- +    find bandit -type f -name "*.pyc" -delete

- +    stestr run {posargs}

- +whitelist_externals =

- +    find

-  passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY

-  

-  [testenv:debug]

- @@ -50,8 +51,12 @@ commands = bandit-baseline -r bandit -ll -ii

-  [testenv:cover]

-  deps = -r{toxinidir}/requirements.txt

-         -r{toxinidir}/test-requirements.txt

- +setenv =

- +    {[testenv]setenv}

- +    PYTHON=coverage run --source bandit --parallel-mode

-  commands =

- -    python setup.py testr --coverage --testr-args='{posargs}'

- +    coverage erase

- +    stestr run '{posargs}'

-      coverage report

-  

-  [testenv:openstack_coverage]

- -- 

- 2.13.6

- 

- From a7a8070426ece60ff1ceb2bd196f67a7339db00c Mon Sep 17 00:00:00 2001

- From: Andreas Jaeger <aj@suse.com>

- Date: Fri, 17 Nov 2017 10:07:29 +0100

- Subject: [PATCH 41/43] Remove setting of version/release from releasenotes

- 

- Release notes are version independent, so remove version/release

- values. We've found that projects now require the service package

- to be installed in order to build release notes, and this is entirely

- due to the current convention of pulling in the version information.

- 

- Release notes should not need installation in order to build, so this

- unnecessary version setting needs to be removed.

- 

- This is needed for new release notes publishing, see

- I56909152975f731a9d2c21b2825b972195e48ee8 and the discussion starting

- at

- http://lists.openstack.org/pipermail/openstack-dev/2017-November/124480.html

- .

- 

- Change-Id: I096e956fa44f0dfa9b8210a221bcbe5afb385634

- ---

-  releasenotes/source/conf.py | 13 ++++---------

-  1 file changed, 4 insertions(+), 9 deletions(-)

- 

- diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py

- index 2982e1c..834b07d 100644

- --- a/releasenotes/source/conf.py

- +++ b/releasenotes/source/conf.py

- @@ -55,17 +55,12 @@ master_doc = 'index'

-  project = u'Bandit Release Notes'

-  copyright = u'2016, Bandit Developers'

-  

- -# The version info for the project you're documenting, acts as replacement for

- -# |version| and |release|, also used in various other places throughout the

- -# built documents.

- -#

- -# The short X.Y version.

- -import pbr.version

- -bandit_version = pbr.version.VersionInfo('bandit')

- +# Release notes do not need a version number in the title, they

- +# cover multiple releases.

-  # The full version, including alpha/beta/rc tags.

- -release = bandit_version.version_string_with_vcs()

- +release = ''

-  # The short X.Y version.

- -version = bandit_version.canonical_version_string()

- +version = ''

-  

-  # The language for content autogenerated by Sphinx. Refer to documentation

-  # for a list of supported languages.

- -- 

- 2.13.6

- 

- From e907ddd94ee58a23850e054be77f5a88a85c28f0 Mon Sep 17 00:00:00 2001

- From: OpenStack Proposal Bot <openstack-infra@lists.openstack.org>

- Date: Thu, 23 Nov 2017 18:40:40 +0000

- Subject: [PATCH 42/43] Updated from global requirements

- 

- Change-Id: Ic98daa2b0750da0240ac1d4f9f4e4bc504a7ac07

- ---

-  requirements.txt      | 2 +-

-  test-requirements.txt | 2 +-

-  2 files changed, 2 insertions(+), 2 deletions(-)

- 

- diff --git a/requirements.txt b/requirements.txt

- index affa923..7f1b79d 100644

- --- a/requirements.txt

- +++ b/requirements.txt

- @@ -3,5 +3,5 @@

-  # process, which may cause wedges in the gate later.

-  GitPython>=1.0.1 # BSD License (3 clause)

-  PyYAML>=3.10 # MIT

- -six>=1.9.0 # MIT

- +six>=1.10.0 # MIT

-  stevedore>=1.20.0 # Apache-2.0

- diff --git a/test-requirements.txt b/test-requirements.txt

- index 1fe8d4e..e41ac9f 100644

- --- a/test-requirements.txt

- +++ b/test-requirements.txt

- @@ -7,7 +7,7 @@ hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0

-  mock>=2.0.0 # BSD

-  stestr>=1.0.0 # Apache-2.0

-  testscenarios>=0.4 # Apache-2.0/BSD

- -testtools>=1.4.0 # MIT

- +testtools>=2.2.0 # MIT

-  oslotest>=1.10.0 # Apache-2.0

-  

-  sphinx>=1.6.2 # BSD

- -- 

- 2.13.6

- 

- From 0b3cd391c1ab1678488f01a7bc0e13160cfa9f55 Mon Sep 17 00:00:00 2001

- From: Marek Cermak <macermak@redhat.com>

- Date: Fri, 24 Nov 2017 17:40:32 +0100

- Subject: [PATCH 43/43] Remove extra section from README.rst

- 

- Follow up patch for review/marek_cermak/formatter-custom.

- 

- Adressing comment by Gage Hugo: remove extra section from README.rst

- 

- Change-Id: I177861d404592ba4b9d7b953bbb983963d53b653

- modified:   README.rst

- ---

-  README.rst | 27 ---------------------------

-  1 file changed, 27 deletions(-)

- 

- diff --git a/README.rst b/README.rst

- index de3773f..589ad60 100644

- --- a/README.rst

- +++ b/README.rst

- @@ -370,33 +370,6 @@ To register your plugin, you have two options:

-          bandit.plugins =

-              mako = bandit_mako

-  

- -

- -Custom Formatting

- ------------------

- -

- -Available tags:

- -

- -::

- -    {abspath}, {relpath}, {line},  {test_id},

- -    {severity}, {msg}, {confidence}, {range}

- -

- -Example usage:

- -

- -  Default template::

- -    bandit -r examples/ --format custom --msg-template \

- -    "{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"

- -

- -  Provides same output as::

- -    bandit -r examples/ --format custom

- -

- -  Tags can also be formatted in python string.format() style::

- -    bandit -r examples/ --format custom --msg-template \

- -    "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"

- -

- -See python documentation for more information about formatting style:

- -https://docs.python.org/3.4/library/string.html

- -

- -

-  Contributing

-  ------------

-  Contributions to Bandit are always welcome! We can be found on

- -- 

- 2.13.6

- 

file modified
+7 -8
@@ -3,11 +3,11 @@ 

  %global with_tests 0

  

  Name: bandit

- Version: 1.4.0

- Release: 14%{?dist}

+ Version: 1.6.2

+ Release: 1%{?dist}

  Summary: A framework for performing security analysis of Python source code

  License: ASL 2.0

- URL: https://wiki.openstack.org/wiki/Security/Projects/Bandit

+ URL: https://github.com/PyCQA/bandit

  Source0: https://files.pythonhosted.org/packages/source/b/%{name}/%{name}-%{version}.tar.gz

  BuildArch: noarch

  Requires: python3-PyYAML
@@ -20,10 +20,6 @@ 

  %endif

  BuildRequires: python3-pbr

  

- Patch0: bandit-1.4.0-2-setup.cfg.patch

- Patch1: bandit-1.4.0-3-formatter-yaml.patch

- Patch2: bandit-1.4.0-4-formatter-custom.patch

- 

  %description

  Bandit provides a framework for performing security analysis of Python source

  code, utilizing the ast module from the Python standard library.
@@ -33,7 +29,7 @@ 

  against those nodes. At the completion of testing, a report is generated

  that lists security issues identified within the target source code.

  %prep

- %autosetup -p1

+ %autosetup

  

  %build

  %{__python3} setup.py build
@@ -58,6 +54,9 @@ 

  %{python3_sitelib}/%{name}-%{version}-py%{python3_version}.egg-info

  

  %changelog

+ * Tue Oct 06 2020 Mikel Olasagasti Uranga <mikel@olasagasti.info> - 1.6.2-1

+ - Version bump

+ 

  * Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.4.0-14

  - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild