eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/blackListCalls.py

changeset 7612
ca1ce1e0fcff
child 7613
382f89c11e27
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/blackListCalls.py	Mon Jun 08 08:17:14 2020 +0200
@@ -0,0 +1,96 @@
+# -*- 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

eric ide

mercurial