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

changeset 7613
382f89c11e27
child 7622
384e2aa5c073
diff -r ca1ce1e0fcff -r 382f89c11e27 eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/djangoSqlInjection.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/djangoSqlInjection.py	Mon Jun 08 20:08:27 2020 +0200
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing checks for potential SQL injections risks.
+"""
+
+#
+# This is a modified version of the one found in the bandit package.
+#
+# Original Copyright (C) 2018 [Victor Torre](https://github.com/ehooo)
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+import ast
+
+
+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
+    """
+    return {
+        "Call": [
+            (checkDjangoExtraUsed, ("S610",)),
+            (checkDjangoRawSqlUsed, ("S611",)),
+        ],
+    }
+
+
+def keywords2dict(keywords):
+    """
+    Function to extract keywords arguments into a dictionary.
+    
+    @param keywords list of keyword nodes
+    @type list of ast.keyword
+    @return dictionary with keyword name and value
+    @rtype dict
+    """
+    kwargs = {}
+    for node in keywords:
+        if isinstance(node, ast.keyword):
+            kwargs[node.arg] = node.value
+    return kwargs
+
+
+def checkDjangoExtraUsed(reportError, context, config):
+    """
+    Function to check for potential SQL injection on extra function.
+    
+    @param reportError function to be used to report errors
+    @type func
+    @param context security context object
+    @type SecurityContext
+    @param config dictionary with configuration data
+    @type dict
+    """
+    if context.callFunctionName == 'extra':
+        kwargs = keywords2dict(context.node.keywords)
+        args = context.node.args
+        if args:
+            if len(args) >= 1:
+                kwargs['select'] = args[0]
+            if len(args) >= 2:
+                kwargs['where'] = args[1]
+            if len(args) >= 3:
+                kwargs['params'] = args[2]
+            if len(args) >= 4:
+                kwargs['tables'] = args[3]
+            if len(args) >= 5:
+                kwargs['order_by'] = args[4]
+            if len(args) >= 6:
+                kwargs['select_params'] = args[5]
+        insecure = False
+        for key in ['where', 'tables']:
+            if key in kwargs:
+                if isinstance(kwargs[key], ast.List):
+                    for val in kwargs[key].elts:
+                        if not isinstance(val, ast.Str):
+                            insecure = True
+                            break
+                else:
+                    insecure = True
+                    break
+        if not insecure and 'select' in kwargs:
+            if isinstance(kwargs['select'], ast.Dict):
+                for k in kwargs['select'].keys:
+                    if not isinstance(k, ast.Str):
+                        insecure = True
+                        break
+                if not insecure:
+                    for v in kwargs['select'].values:
+                        if not isinstance(v, ast.Str):
+                            insecure = True
+                            break
+            else:
+                insecure = True
+        
+        if insecure:
+            reportError(
+                context.node.lineno - 1,
+                context.node.col_offset,
+                "S610",
+                "M",
+                "M"
+            )
+
+
+def checkDjangoRawSqlUsed(reportError, context, config):
+    """
+    Function to check for potential SQL injection on RawSQL function.
+    
+    @param reportError function to be used to report errors
+    @type func
+    @param context security context object
+    @type SecurityContext
+    @param config dictionary with configuration data
+    @type dict
+    """
+    if context.isModuleImportedLike('django.db.models'):
+        if context.callFunctionName == 'RawSQL':
+            sql = context.node.args[0]
+            if not isinstance(sql, ast.Str):
+                reportError(
+                    context.node.lineno - 1,
+                    context.node.col_offset,
+                    "S611",
+                    "M",
+                    "M"
+                )

eric ide

mercurial