Mon, 08 Jun 2020 08:17:14 +0200
Code Style Checker: started to implement checker for security related issues.
# -*- coding: utf-8 -*- # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing checks for blacklisted methods and functions. """ import ast import fnmatch _blacklists = { 'S301': ([ 'pickle.loads', 'pickle.load', 'pickle.Unpickler', 'cPickle.loads', 'cPickle.load', 'cPickle.Unpickler', 'dill.loads', 'dill.load', 'dill.Unpickler', 'shelve.open', 'shelve.DbfilenameShelf'], "M"), 'S302': ([ 'marshal.load', 'marshal.loads'], "M"), 'S303': ([ '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', 'Cryptodome.Hash.SHA.new', 'cryptography.hazmat.primitives.hashes.MD5', 'cryptography.hazmat.primitives.hashes.SHA1'], "M"), } def getChecks(): """ Public method to get a dictionary with checks handled by this module. @return dictionary containing checker lists containing checker function and list of codes @rtype dict """ # TODO: should be list of tuples return { "Call": (checkBlacklist, tuple(_blacklists.keys())), } def checkBlacklist(reportError, context, config): nodeType = context.node.__class__.__name__ if nodeType == 'Call': func = context.node.func if isinstance(func, ast.Name) and func.id == '__import__': if len(context.node.args): if isinstance(context.node.args[0], ast.Str): name = context.node.args[0].s else: name = "UNKNOWN" else: name = "" # handle '__import__()' else: name = context.callFunctionNameQual # In the case the Call is an importlib.import, treat the first # argument name as an actual import module name. # Will produce None if argument is not a literal or identifier. if name in ["importlib.import_module", "importlib.__import__"]: name = context.call_args[0] for code in _blacklists: qualnames, severity = _blacklists[code] for qualname in qualnames: if name and fnmatch.fnmatch(name, qualname): return reportError( context.node.lineno, context.node.col_offset, code, "M", "H" ) return None