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

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

eric ide

mercurial