src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/Checks/prohibitedCalls.py

branch
eric7
changeset 10503
6a37b6ac3928
parent 10439
21c28b0f9e41
child 10507
d1c6608155ef
equal deleted inserted replaced
10502:89b8e0a67fde 10503:6a37b6ac3928
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2020 - 2024 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing checks for prohibited methods and functions.
8 """
9
10 #
11 # This is a modified version of the one found in the bandit package.
12 #
13 # Original Copyright 2016 Hewlett-Packard Development Company, L.P.
14 #
15 # SPDX-License-Identifier: Apache-2.0
16 #
17
18 import ast
19 import fnmatch
20 import sys
21
22 import AstUtilities
23
24 _prohibitedCalls = {
25 "S301": (
26 [
27 "pickle.loads",
28 "pickle.load",
29 "pickle.Unpickler",
30 "cPickle.loads",
31 "cPickle.load",
32 "cPickle.Unpickler",
33 "dill.loads",
34 "dill.load",
35 "dill.Unpickler",
36 "shelve.open",
37 "shelve.DbfilenameShelf",
38 ],
39 "M",
40 ),
41 "S302": (["marshal.load", "marshal.loads"], "M"),
42 }
43 if sys.version_info >= (3, 9):
44 _prohibitedCalls["S303"] = (
45 [
46 "Crypto.Hash.MD2.new",
47 "Crypto.Hash.MD4.new",
48 "Crypto.Hash.MD5.new",
49 "Crypto.Hash.SHA.new",
50 "Cryptodome.Hash.MD2.new",
51 "Cryptodome.Hash.MD4.new",
52 "Cryptodome.Hash.MD5.new",
53 "Cryptodome.Hash.SHA.new",
54 "cryptography.hazmat.primitives.hashes.MD5",
55 "cryptography.hazmat.primitives.hashes.SHA1",
56 ],
57 "M",
58 )
59 else:
60 _prohibitedCalls["S303"] = (
61 [
62 "hashlib.md4",
63 "hashlib.md5",
64 "hashlib.sha",
65 "hashlib.sha1",
66 "Crypto.Hash.MD2.new",
67 "Crypto.Hash.MD4.new",
68 "Crypto.Hash.MD5.new",
69 "Crypto.Hash.SHA.new",
70 "Cryptodome.Hash.MD2.new",
71 "Cryptodome.Hash.MD4.new",
72 "Cryptodome.Hash.MD5.new",
73 "Cryptodome.Hash.SHA.new",
74 "cryptography.hazmat.primitives.hashes.MD5",
75 "cryptography.hazmat.primitives.hashes.SHA1",
76 ],
77 "M",
78 )
79
80 _prohibitedCalls.update(
81 {
82 "S304": (
83 [
84 "Crypto.Cipher.ARC2.new",
85 "Crypto.Cipher.ARC4.new",
86 "Crypto.Cipher.Blowfish.new",
87 "Crypto.Cipher.DES.new",
88 "Crypto.Cipher.XOR.new",
89 "Cryptodome.Cipher.ARC2.new",
90 "Cryptodome.Cipher.ARC4.new",
91 "Cryptodome.Cipher.Blowfish.new",
92 "Cryptodome.Cipher.DES.new",
93 "Cryptodome.Cipher.XOR.new",
94 "cryptography.hazmat.primitives.ciphers.algorithms.ARC4",
95 "cryptography.hazmat.primitives.ciphers.algorithms.Blowfish",
96 "cryptography.hazmat.primitives.ciphers.algorithms.IDEA",
97 ],
98 "H",
99 ),
100 "S305": (["cryptography.hazmat.primitives.ciphers.modes.ECB"], "M"),
101 "S306": (["tempfile.mktemp"], "M"),
102 "S307": (["eval"], "M"),
103 "S308": (["django.utils.safestring.mark_safe"], "M"),
104 "S309": (
105 [
106 "httplib.HTTPSConnection",
107 "http.client.HTTPSConnection",
108 "six.moves.http_client.HTTPSConnection",
109 ],
110 "M",
111 ),
112 "S310": (
113 [
114 "urllib.urlopen",
115 "urllib.request.urlopen",
116 "urllib.urlretrieve",
117 "urllib.request.urlretrieve",
118 "urllib.URLopener",
119 "urllib.request.URLopener",
120 "urllib.FancyURLopener",
121 "urllib.request.FancyURLopener",
122 "urllib2.urlopen",
123 "urllib2.Request",
124 "six.moves.urllib.request.urlopen",
125 "six.moves.urllib.request.urlretrieve",
126 "six.moves.urllib.request.URLopener",
127 "six.moves.urllib.request.FancyURLopener",
128 ],
129 "",
130 ),
131 "S311": (
132 [
133 "random.random",
134 "random.randrange",
135 "random.randint",
136 "random.choice",
137 "random.choices",
138 "random.uniform",
139 "random.triangular",
140 ],
141 "L",
142 ),
143 "S312": (["telnetlib.*"], "H"),
144 "S313": (
145 [
146 "xml.etree.cElementTree.parse",
147 "xml.etree.cElementTree.iterparse",
148 "xml.etree.cElementTree.fromstring",
149 "xml.etree.cElementTree.XMLParser",
150 ],
151 "M",
152 ),
153 "S314": (
154 [
155 "xml.etree.ElementTree.parse",
156 "xml.etree.ElementTree.iterparse",
157 "xml.etree.ElementTree.fromstring",
158 "xml.etree.ElementTree.XMLParser",
159 ],
160 "M",
161 ),
162 "S315": (["xml.sax.expatreader.create_parser"], "M"),
163 "S316": (
164 ["xml.dom.expatbuilder.parse", "xml.dom.expatbuilder.parseString"],
165 "M",
166 ),
167 "S317": (["xml.sax.parse", "xml.sax.parseString", "xml.sax.make_parser"], "M"),
168 "S318": (["xml.dom.minidom.parse", "xml.dom.minidom.parseString"], "M"),
169 "S319": (["xml.dom.pulldom.parse", "xml.dom.pulldom.parseString"], "M"),
170 "S320": (
171 [
172 "lxml.etree.parse",
173 "lxml.etree.fromstring",
174 "lxml.etree.RestrictedElement",
175 "lxml.etree.GlobalParserTLS",
176 "lxml.etree.getDefaultParser",
177 "lxml.etree.check_docinfo",
178 ],
179 "M",
180 ),
181 "S321": (["ftplib.*"], "H"),
182 "S322": (["input"], "H"),
183 "S323": (["ssl._create_unverified_context"], "M"),
184 "S324": (["os.tempnam", "os.tmpnam"], "M"),
185 }
186 )
187
188
189 def getChecks():
190 """
191 Public method to get a dictionary with checks handled by this module.
192
193 @return dictionary containing checker lists containing checker function and
194 list of codes
195 @rtype dict
196 """
197 return {
198 "Call": [
199 (checkProhibitedCalls, tuple(_prohibitedCalls)),
200 ],
201 }
202
203
204 def checkProhibitedCalls(reportError, context, config): # noqa: U100
205 """
206 Function to check for prohibited method calls.
207
208 @param reportError function to be used to report errors
209 @type func
210 @param context security context object
211 @type SecurityContext
212 @param config dictionary with configuration data
213 @type dict
214 """
215 nodeType = context.node.__class__.__name__
216
217 if nodeType == "Call":
218 func = context.node.func
219 if isinstance(func, ast.Name) and func.id == "__import__":
220 if len(context.node.args):
221 if AstUtilities.isString(context.node.args[0]):
222 name = context.node.args[0].s
223 else:
224 name = "UNKNOWN"
225 else:
226 name = "" # handle '__import__()'
227 else:
228 name = context.callFunctionNameQual
229 # In the case the Call is an importlib.import, treat the first
230 # argument name as an actual import module name.
231 # Will produce None if argument is not a literal or identifier.
232 if name in ["importlib.import_module", "importlib.__import__"]:
233 name = context.callArgs[0]
234
235 for code in _prohibitedCalls:
236 qualnames, severity = _prohibitedCalls[code]
237 for qualname in qualnames:
238 if name and fnmatch.fnmatch(name, qualname):
239 reportError(
240 context.node.lineno - 1,
241 context.node.col_offset,
242 code,
243 severity,
244 "H",
245 name,
246 )

eric ide

mercurial