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

Mon, 08 Jun 2020 08:17:14 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 08 Jun 2020 08:17:14 +0200
changeset 7612
ca1ce1e0fcff
child 7613
382f89c11e27
permissions
-rw-r--r--

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

eric ide

mercurial