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

changeset 7614
646742c260bd
child 7622
384e2aa5c073
equal deleted inserted replaced
7613:382f89c11e27 7614:646742c260bd
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing checks for potentially hardcoded passwords.
8 """
9
10 #
11 # This is a modified version of the one found in the bandit package.
12 #
13 # Original Copyright 2014 Hewlett-Packard Development Company, L.P.
14 #
15 # SPDX-License-Identifier: Apache-2.0
16 #
17
18 import ast
19 import re
20 import sys
21
22 RE_WORDS = "(pas+wo?r?d|pass(phrase)?|pwd|token|secrete?|ken+wort|geheim)"
23 RE_CANDIDATES = re.compile(
24 '(^{0}$|_{0}_|^{0}_|_{0}$)'.format(RE_WORDS),
25 re.IGNORECASE
26 )
27
28
29 def getChecks():
30 """
31 Public method to get a dictionary with checks handled by this module.
32
33 @return dictionary containing checker lists containing checker function and
34 list of codes
35 @rtype dict
36 """
37 return {
38 "Str": [
39 (checkHardcodedPasswordAsString, ("S105",)),
40 ],
41 "Call": [
42 (checkHardcodedPasswordAsFunctionArg, ("S106",)),
43 ],
44 "FunctionDef": [
45 (checkHardcodedPasswordAsDefault, ("S107",)),
46 ],
47 }
48
49
50 def checkHardcodedPasswordAsString(reportError, context, config):
51 """
52 Function to check for use of hardcoded password strings.
53
54 @param reportError function to be used to report errors
55 @type func
56 @param context security context object
57 @type SecurityContext
58 @param config dictionary with configuration data
59 @type dict
60 """
61 node = context.node
62 if isinstance(node._securityParent, ast.Assign):
63 # looks for "candidate='some_string'"
64 for targ in node._securityParent.targets:
65 if isinstance(targ, ast.Name) and RE_CANDIDATES.search(targ.id):
66 reportError(
67 context.node.lineno - 1,
68 context.node.col_offset,
69 "S105",
70 "L",
71 "M",
72 node.s
73 )
74
75 elif (
76 isinstance(node._securityParent, ast.Index) and
77 RE_CANDIDATES.search(node.s)
78 ):
79 # looks for "dict[candidate]='some_string'"
80 # assign -> subscript -> index -> string
81 assign = node._securityParent._securityParent._securityParent
82 if (
83 isinstance(assign, ast.Assign) and
84 isinstance(assign.value, ast.Str)
85 ):
86 reportError(
87 context.node.lineno - 1,
88 context.node.col_offset,
89 "S105",
90 "L",
91 "M",
92 assign.value.s
93 )
94
95 elif isinstance(node._securityParent, ast.Compare):
96 # looks for "candidate == 'some_string'"
97 comp = node._securityParent
98 if isinstance(comp.left, ast.Name):
99 if RE_CANDIDATES.search(comp.left.id):
100 if isinstance(comp.comparators[0], ast.Str):
101 reportError(
102 context.node.lineno - 1,
103 context.node.col_offset,
104 "S105",
105 "L",
106 "M",
107 comp.comparators[0].s
108 )
109
110
111 def checkHardcodedPasswordAsFunctionArg(reportError, context, config):
112 """
113 Function to check for use of hard-coded password function arguments.
114
115 @param reportError function to be used to report errors
116 @type func
117 @param context security context object
118 @type SecurityContext
119 @param config dictionary with configuration data
120 @type dict
121 """
122 # looks for "function(candidate='some_string')"
123 for kw in context.node.keywords:
124 if isinstance(kw.value, ast.Str) and RE_CANDIDATES.search(kw.arg):
125 reportError(
126 context.node.lineno - 1,
127 context.node.col_offset,
128 "S106",
129 "L",
130 "M",
131 kw.value.s
132 )
133
134
135 def checkHardcodedPasswordAsDefault(reportError, context, config):
136 """
137 Function to check for use of hard-coded password argument defaults.
138
139 @param reportError function to be used to report errors
140 @type func
141 @param context security context object
142 @type SecurityContext
143 @param config dictionary with configuration data
144 @type dict
145 """
146 # looks for "def function(candidate='some_string')"
147
148 # this pads the list of default values with "None" if nothing is given
149 defs = [None] * (len(context.node.args.args) -
150 len(context.node.args.defaults))
151 defs.extend(context.node.args.defaults)
152
153 # go through all (param, value)s and look for candidates
154 for key, val in zip(context.node.args.args, defs):
155 isPy3Arg = True
156 if sys.version_info[0] > 2:
157 isPy3Arg = isinstance(key, ast.arg)
158 if isinstance(key, ast.Name) or isPy3Arg:
159 check = key.arg if sys.version_info[0] > 2 else key.id # Py3
160 if isinstance(val, ast.Str) and RE_CANDIDATES.search(check):
161 reportError(
162 context.node.lineno - 1,
163 context.node.col_offset,
164 "S107",
165 "L",
166 "M",
167 val.s
168 )

eric ide

mercurial