src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityChecker.py

branch
eric7
changeset 11150
73d80859079c
parent 11147
dee6e106b4d3
equal deleted inserted replaced
11149:fc45672fae42 11150:73d80859079c
6 """ 6 """
7 Module implementing the security checker. 7 Module implementing the security checker.
8 """ 8 """
9 9
10 import collections 10 import collections
11 import copy 11
12 from CodeStyleTopicChecker import CodeStyleTopicChecker
12 13
13 from . import Checks 14 from . import Checks
14 from .SecurityNodeVisitor import SecurityNodeVisitor 15 from .SecurityNodeVisitor import SecurityNodeVisitor
15 16
16 17
17 class SecurityChecker: 18 class SecurityChecker(CodeStyleTopicChecker):
18 """ 19 """
19 Class implementing a checker for security issues. 20 Class implementing a checker for security issues.
20 """ 21 """
21 22
22 Codes = [ 23 Codes = [
115 "S-703", 116 "S-703",
116 # hardcoded AWS passwords 117 # hardcoded AWS passwords
117 "S-801", 118 "S-801",
118 "S-802", 119 "S-802",
119 ] 120 ]
121 Category = "S"
120 122
121 def __init__(self, source, filename, tree, select, ignore, expected, repeat, args): 123 def __init__(self, source, filename, tree, select, ignore, expected, repeat, args):
122 """ 124 """
123 Constructor 125 Constructor
124 126
137 @param repeat flag indicating to report each occurrence of a code 139 @param repeat flag indicating to report each occurrence of a code
138 @type bool 140 @type bool
139 @param args dictionary of arguments for the security checks 141 @param args dictionary of arguments for the security checks
140 @type dict 142 @type dict
141 """ 143 """
142 self.__select = tuple(select) 144 super().__init__(
143 self.__ignore = tuple(ignore) 145 SecurityChecker.Category,
144 self.__expected = expected[:] 146 source,
145 self.__repeat = repeat 147 filename,
146 self.__filename = filename 148 tree,
147 self.__source = source[:] 149 select,
148 self.__tree = copy.deepcopy(tree) 150 ignore,
149 self.__args = args 151 expected,
150 152 repeat,
151 # statistics counters 153 args,
152 self.counters = {} 154 )
153
154 # collection of detected errors
155 self.errors = []
156 155
157 checkersWithCodes = Checks.generateCheckersDict() 156 checkersWithCodes = Checks.generateCheckersDict()
158 157
159 self.__checkers = collections.defaultdict(list) 158 self.__checkers = collections.defaultdict(list)
160 for checkType, checkersList in checkersWithCodes.items(): 159 for checkType, checkersList in checkersWithCodes.items():
161 for checker, codes in checkersList: 160 for checker, codes in checkersList:
162 if any(not (code and self.__ignoreCode(code)) for code in codes): 161 if any(
162 not (msgCode and self._ignoreCode(msgCode)) for msgCode in codes
163 ):
163 self.__checkers[checkType].append(checker) 164 self.__checkers[checkType].append(checker)
164 165
165 def __ignoreCode(self, code): 166 def addError(self, lineNumber, offset, msgCode, severity, confidence, *args):
166 """
167 Private method to check if the message code should be ignored.
168
169 @param code message code to check for
170 @type str
171 @return flag indicating to ignore the given code
172 @rtype bool
173 """
174 return code in self.__ignore or (
175 code.startswith(self.__ignore) and not code.startswith(self.__select)
176 )
177
178 def reportError(self, lineNumber, offset, code, severity, confidence, *args):
179 """ 167 """
180 Public method to record an issue. 168 Public method to record an issue.
181 169
182 @param lineNumber line number of the issue 170 @param lineNumber line number of the issue
183 @type int 171 @type int
184 @param offset position within line of the issue 172 @param offset position within line of the issue
185 @type int 173 @type int
186 @param code message code 174 @param msgCode message code
187 @type str 175 @type str
188 @param severity severity code (H = high, M = medium, L = low, 176 @param severity severity code (H = high, M = medium, L = low,
189 U = undefined) 177 U = undefined)
190 @type str 178 @type str
191 @param confidence confidence code (H = high, M = medium, L = low, 179 @param confidence confidence code (H = high, M = medium, L = low,
192 U = undefined) 180 U = undefined)
193 @type str 181 @type str
194 @param args arguments for the message 182 @param args arguments for the message
195 @type list 183 @type list
196 """ 184 """
197 if self.__ignoreCode(code): 185 if self._ignoreCode(msgCode):
198 return 186 return
199 187
200 if code in self.counters: 188 if msgCode in self.counters:
201 self.counters[code] += 1 189 self.counters[msgCode] += 1
202 else: 190 else:
203 self.counters[code] = 1 191 self.counters[msgCode] = 1
204 192
205 # Don't care about expected codes 193 # Don't care about expected codes
206 if code in self.__expected: 194 if msgCode in self.expected:
207 return 195 return
208 196
209 if code and (self.counters[code] == 1 or self.__repeat): 197 if msgCode and (self.counters[msgCode] == 1 or self.repeat):
210 # record the issue with one based line number 198 # record the issue with one based line number
211 self.errors.append( 199 self.errors.append(
212 { 200 {
213 "file": self.__filename, 201 "file": self.filename,
214 "line": lineNumber + 1, 202 "line": lineNumber + 1,
215 "offset": offset, 203 "offset": offset,
216 "code": code, 204 "code": msgCode,
217 "args": args, 205 "args": args,
218 "severity": severity, 206 "severity": severity,
219 "confidence": confidence, 207 "confidence": confidence,
220 } 208 }
221 ) 209 )
225 Public method to get the configuration dictionary. 213 Public method to get the configuration dictionary.
226 214
227 @return dictionary containing the configuration 215 @return dictionary containing the configuration
228 @rtype dict 216 @rtype dict
229 """ 217 """
230 return self.__args 218 return self.args
231 219
232 def run(self): 220 def run(self):
233 """ 221 """
234 Public method to check the given source against security related 222 Public method to check the given source against security related
235 conditions. 223 conditions.
236 """ 224 """
237 if not self.__filename: 225 if not self.filename:
238 # don't do anything, if essential data is missing 226 # don't do anything, if essential data is missing
239 return 227 return
240 228
241 if not self.__checkers: 229 if not self.__checkers:
242 # don't do anything, if no codes were selected 230 # don't do anything, if no codes were selected
243 return 231 return
244 232
245 securityNodeVisitor = SecurityNodeVisitor( 233 securityNodeVisitor = SecurityNodeVisitor(
246 self, self.__checkers, self.__filename, self.__source 234 self, self.__checkers, self.filename, self.source
247 ) 235 )
248 securityNodeVisitor.generic_visit(self.__tree) 236 securityNodeVisitor.generic_visit(self.tree)
249 securityNodeVisitor.checkFile() 237 securityNodeVisitor.checkFile()

eric ide

mercurial