Skip to content

Commit c2c336d

Browse files
authored
Revert "Start testing with 3.14 alphas" (#1217)
Revert "Start testing with 3.14 alphas (#1189)" This reverts commit 13d3406.
1 parent e58379c commit c2c336d

12 files changed

+76
-83
lines changed

.github/workflows/pythonpackage.yml

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ jobs:
5252
["3.11", "311"],
5353
["3.12", "312"],
5454
["3.13", "313"],
55-
["3.14.0-alpha - 3.14", "314"],
5655
]
5756
os: [ubuntu-latest, macos-latest]
5857
runs-on: ${{ matrix.os }}

bandit/core/blacklisting.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ def blacklist(context, config):
3535
func = context.node.func
3636
if isinstance(func, ast.Name) and func.id == "__import__":
3737
if len(context.node.args):
38-
if isinstance(context.node.args[0], ast.Constant):
39-
name = context.node.args[0].value
38+
if isinstance(context.node.args[0], ast.Str):
39+
name = context.node.args[0].s
4040
else:
4141
# TODO(??): import through a variable, need symbol tab
4242
name = "UNKNOWN"

bandit/core/context.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,11 @@ def _get_literal_value(self, literal):
178178
:param literal: The AST literal to convert
179179
:return: The value of the AST literal
180180
"""
181-
if isinstance(literal, ast.Constant):
182-
if isinstance(literal.value, bool):
183-
literal_value = str(literal.value)
184-
elif literal.value is None:
185-
literal_value = str(literal.value)
186-
else:
187-
literal_value = literal.value
181+
if isinstance(literal, ast.Num):
182+
literal_value = literal.n
183+
184+
elif isinstance(literal, ast.Str):
185+
literal_value = literal.s
188186

189187
elif isinstance(literal, ast.List):
190188
return_list = list()
@@ -207,9 +205,19 @@ def _get_literal_value(self, literal):
207205
elif isinstance(literal, ast.Dict):
208206
literal_value = dict(zip(literal.keys, literal.values))
209207

208+
elif isinstance(literal, ast.Ellipsis):
209+
# what do we want to do with this?
210+
literal_value = None
211+
210212
elif isinstance(literal, ast.Name):
211213
literal_value = literal.id
212214

215+
elif isinstance(literal, ast.NameConstant):
216+
literal_value = str(literal.value)
217+
218+
elif isinstance(literal, ast.Bytes):
219+
literal_value = literal.s
220+
213221
else:
214222
literal_value = None
215223

bandit/core/node_visitor.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def visit_Str(self, node):
168168
:param node: The node that is being inspected
169169
:return: -
170170
"""
171-
self.context["str"] = node.value
171+
self.context["str"] = node.s
172172
if not isinstance(node._bandit_parent, ast.Expr): # docstring
173173
self.context["linerange"] = b_utils.linerange(node._bandit_parent)
174174
self.update_scores(self.tester.run_tests(self.context, "Str"))
@@ -181,7 +181,7 @@ def visit_Bytes(self, node):
181181
:param node: The node that is being inspected
182182
:return: -
183183
"""
184-
self.context["bytes"] = node.value
184+
self.context["bytes"] = node.s
185185
if not isinstance(node._bandit_parent, ast.Expr): # docstring
186186
self.context["linerange"] = b_utils.linerange(node._bandit_parent)
187187
self.update_scores(self.tester.run_tests(self.context, "Bytes"))

bandit/core/utils.py

+4-18
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,12 @@ def linerange(node):
273273
def concat_string(node, stop=None):
274274
"""Builds a string from a ast.BinOp chain.
275275
276-
This will build a string from a series of ast.Constant nodes wrapped in
276+
This will build a string from a series of ast.Str nodes wrapped in
277277
ast.BinOp nodes. Something like "a" + "b" + "c" or "a %s" % val etc.
278278
The provided node can be any participant in the BinOp chain.
279279
280-
:param node: (ast.Constant or ast.BinOp) The node to process
281-
:param stop: (ast.Constant or ast.BinOp) Optional base node to stop at
280+
:param node: (ast.Str or ast.BinOp) The node to process
281+
:param stop: (ast.Str or ast.BinOp) Optional base node to stop at
282282
:returns: (Tuple) the root node of the expression, the string value
283283
"""
284284

@@ -300,10 +300,7 @@ def _get(node, bits, stop=None):
300300
node = node._bandit_parent
301301
if isinstance(node, ast.BinOp):
302302
_get(node, bits, stop)
303-
return (
304-
node,
305-
" ".join([x.value for x in bits if isinstance(x, ast.Constant)]),
306-
)
303+
return (node, " ".join([x.s for x in bits if isinstance(x, ast.Str)]))
307304

308305

309306
def get_called_name(node):
@@ -364,17 +361,6 @@ def parse_ini_file(f_loc):
364361
def check_ast_node(name):
365362
"Check if the given name is that of a valid AST node."
366363
try:
367-
# These ast Node types don't exist in Python 3.14, but plugins may
368-
# still check on them.
369-
if sys.version_info >= (3, 14) and name in (
370-
"Num",
371-
"Str",
372-
"Ellipsis",
373-
"NameConstant",
374-
"Bytes",
375-
):
376-
return name
377-
378364
node = getattr(ast, name)
379365
if issubclass(node, ast.AST):
380366
return name

bandit/plugins/django_sql_injection.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def django_extra_used(context):
6868
if key in kwargs:
6969
if isinstance(kwargs[key], ast.List):
7070
for val in kwargs[key].elts:
71-
if not isinstance(val, ast.Constant):
71+
if not isinstance(val, ast.Str):
7272
insecure = True
7373
break
7474
else:
@@ -77,12 +77,12 @@ def django_extra_used(context):
7777
if not insecure and "select" in kwargs:
7878
if isinstance(kwargs["select"], ast.Dict):
7979
for k in kwargs["select"].keys:
80-
if not isinstance(k, ast.Constant):
80+
if not isinstance(k, ast.Str):
8181
insecure = True
8282
break
8383
if not insecure:
8484
for v in kwargs["select"].values:
85-
if not isinstance(v, ast.Constant):
85+
if not isinstance(v, ast.Str):
8686
insecure = True
8787
break
8888
else:
@@ -135,7 +135,7 @@ def django_rawsql_used(context):
135135
kwargs = keywords2dict(context.node.keywords)
136136
sql = kwargs["sql"]
137137

138-
if not isinstance(sql, ast.Constant):
138+
if not isinstance(sql, ast.Str):
139139
return bandit.Issue(
140140
severity=bandit.MEDIUM,
141141
confidence=bandit.MEDIUM,

bandit/plugins/django_xss.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def evaluate_var(xss_var, parent, until, ignore_nodes=None):
9696
break
9797
to = analyser.is_assigned(node)
9898
if to:
99-
if isinstance(to, ast.Constant):
99+
if isinstance(to, ast.Str):
100100
secure = True
101101
elif isinstance(to, ast.Name):
102102
secure = evaluate_var(to, parent, to.lineno, ignore_nodes)
@@ -105,7 +105,7 @@ def evaluate_var(xss_var, parent, until, ignore_nodes=None):
105105
elif isinstance(to, (list, tuple)):
106106
num_secure = 0
107107
for some_to in to:
108-
if isinstance(some_to, ast.Constant):
108+
if isinstance(some_to, ast.Str):
109109
num_secure += 1
110110
elif isinstance(some_to, ast.Name):
111111
if evaluate_var(
@@ -131,10 +131,7 @@ def evaluate_call(call, parent, ignore_nodes=None):
131131
secure = False
132132
evaluate = False
133133
if isinstance(call, ast.Call) and isinstance(call.func, ast.Attribute):
134-
if (
135-
isinstance(call.func.value, ast.Constant)
136-
and call.func.attr == "format"
137-
):
134+
if isinstance(call.func.value, ast.Str) and call.func.attr == "format":
138135
evaluate = True
139136
if call.keywords:
140137
evaluate = False # TODO(??) get support for this
@@ -143,7 +140,7 @@ def evaluate_call(call, parent, ignore_nodes=None):
143140
args = list(call.args)
144141
num_secure = 0
145142
for arg in args:
146-
if isinstance(arg, ast.Constant):
143+
if isinstance(arg, ast.Str):
147144
num_secure += 1
148145
elif isinstance(arg, ast.Name):
149146
if evaluate_var(arg, parent, call.lineno, ignore_nodes):
@@ -170,7 +167,7 @@ def evaluate_call(call, parent, ignore_nodes=None):
170167
def transform2call(var):
171168
if isinstance(var, ast.BinOp):
172169
is_mod = isinstance(var.op, ast.Mod)
173-
is_left_str = isinstance(var.left, ast.Constant)
170+
is_left_str = isinstance(var.left, ast.Str)
174171
if is_mod and is_left_str:
175172
new_call = ast.Call()
176173
new_call.args = []
@@ -215,7 +212,7 @@ def check_risk(node):
215212
secure = evaluate_call(xss_var, parent)
216213
elif isinstance(xss_var, ast.BinOp):
217214
is_mod = isinstance(xss_var.op, ast.Mod)
218-
is_left_str = isinstance(xss_var.left, ast.Constant)
215+
is_left_str = isinstance(xss_var.left, ast.Str)
219216
if is_mod and is_left_str:
220217
parent = node._bandit_parent
221218
while not isinstance(parent, (ast.Module, ast.FunctionDef)):
@@ -275,5 +272,5 @@ def django_mark_safe(context):
275272
]
276273
if context.call_function_name in affected_functions:
277274
xss = context.node.args[0]
278-
if not isinstance(xss, ast.Constant):
275+
if not isinstance(xss, ast.Str):
279276
return check_risk(context.node)

bandit/plugins/general_hardcoded_password.py

+16-16
Original file line numberDiff line numberDiff line change
@@ -83,45 +83,45 @@ def hardcoded_password_string(context):
8383
# looks for "candidate='some_string'"
8484
for targ in node._bandit_parent.targets:
8585
if isinstance(targ, ast.Name) and RE_CANDIDATES.search(targ.id):
86-
return _report(node.value)
86+
return _report(node.s)
8787
elif isinstance(targ, ast.Attribute) and RE_CANDIDATES.search(
8888
targ.attr
8989
):
90-
return _report(node.value)
90+
return _report(node.s)
9191

9292
elif isinstance(
9393
node._bandit_parent, ast.Subscript
94-
) and RE_CANDIDATES.search(node.value):
94+
) and RE_CANDIDATES.search(node.s):
9595
# Py39+: looks for "dict[candidate]='some_string'"
9696
# subscript -> index -> string
9797
assign = node._bandit_parent._bandit_parent
9898
if isinstance(assign, ast.Assign) and isinstance(
99-
assign.value, ast.Constant
99+
assign.value, ast.Str
100100
):
101-
return _report(assign.value.value)
101+
return _report(assign.value.s)
102102

103103
elif isinstance(node._bandit_parent, ast.Index) and RE_CANDIDATES.search(
104-
node.value
104+
node.s
105105
):
106106
# looks for "dict[candidate]='some_string'"
107107
# assign -> subscript -> index -> string
108108
assign = node._bandit_parent._bandit_parent._bandit_parent
109109
if isinstance(assign, ast.Assign) and isinstance(
110-
assign.value, ast.Constant
110+
assign.value, ast.Str
111111
):
112-
return _report(assign.value.value)
112+
return _report(assign.value.s)
113113

114114
elif isinstance(node._bandit_parent, ast.Compare):
115115
# looks for "candidate == 'some_string'"
116116
comp = node._bandit_parent
117117
if isinstance(comp.left, ast.Name):
118118
if RE_CANDIDATES.search(comp.left.id):
119-
if isinstance(comp.comparators[0], ast.Constant):
120-
return _report(comp.comparators[0].value)
119+
if isinstance(comp.comparators[0], ast.Str):
120+
return _report(comp.comparators[0].s)
121121
elif isinstance(comp.left, ast.Attribute):
122122
if RE_CANDIDATES.search(comp.left.attr):
123-
if isinstance(comp.comparators[0], ast.Constant):
124-
return _report(comp.comparators[0].value)
123+
if isinstance(comp.comparators[0], ast.Str):
124+
return _report(comp.comparators[0].s)
125125

126126

127127
@test.checks("Call")
@@ -176,8 +176,8 @@ def hardcoded_password_funcarg(context):
176176
"""
177177
# looks for "function(candidate='some_string')"
178178
for kw in context.node.keywords:
179-
if isinstance(kw.value, ast.Constant) and RE_CANDIDATES.search(kw.arg):
180-
return _report(kw.value.value)
179+
if isinstance(kw.value, ast.Str) and RE_CANDIDATES.search(kw.arg):
180+
return _report(kw.value.s)
181181

182182

183183
@test.checks("FunctionDef")
@@ -242,5 +242,5 @@ def hardcoded_password_default(context):
242242
# go through all (param, value)s and look for candidates
243243
for key, val in zip(context.node.args.args, defs):
244244
if isinstance(key, (ast.Name, ast.arg)):
245-
if isinstance(val, ast.Constant) and RE_CANDIDATES.search(key.arg):
246-
return _report(val.value)
245+
if isinstance(val, ast.Str) and RE_CANDIDATES.search(key.arg):
246+
return _report(val.s)

bandit/plugins/injection_shell.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
def _evaluate_shell_call(context):
18-
no_formatting = isinstance(context.node.args[0], ast.Constant)
18+
no_formatting = isinstance(context.node.args[0], ast.Str)
1919

2020
if no_formatting:
2121
return bandit.LOW
@@ -83,14 +83,16 @@ def has_shell(context):
8383
for key in keywords:
8484
if key.arg == "shell":
8585
val = key.value
86-
if isinstance(val, ast.Constant):
87-
result = bool(val.value)
86+
if isinstance(val, ast.Num):
87+
result = bool(val.n)
8888
elif isinstance(val, ast.List):
8989
result = bool(val.elts)
9090
elif isinstance(val, ast.Dict):
9191
result = bool(val.keys)
9292
elif isinstance(val, ast.Name) and val.id in ["False", "None"]:
9393
result = False
94+
elif isinstance(val, ast.NameConstant):
95+
result = val.value
9496
else:
9597
result = True
9698
return result
@@ -685,9 +687,7 @@ def start_process_with_partial_path(context, config):
685687
node = node.elts[0]
686688

687689
# make sure the param is a string literal and not a var name
688-
if isinstance(node, ast.Constant) and not full_path_match.match(
689-
node.value
690-
):
690+
if isinstance(node, ast.Str) and not full_path_match.match(node.s):
691691
return bandit.Issue(
692692
severity=bandit.LOW,
693693
confidence=bandit.HIGH,

bandit/plugins/injection_sql.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def _evaluate_ast(node):
9696
elif isinstance(
9797
node._bandit_parent, ast.Attribute
9898
) and node._bandit_parent.attr in ("format", "replace"):
99-
statement = node.value
99+
statement = node.s
100100
# Hierarchy for "".format() is Wrapper -> Call -> Attribute -> Str
101101
wrapper = node._bandit_parent._bandit_parent._bandit_parent
102102
if node._bandit_parent.attr == "replace":
@@ -107,14 +107,14 @@ def _evaluate_ast(node):
107107
substrings = [
108108
child
109109
for child in node._bandit_parent.values
110-
if isinstance(child, ast.Constant)
110+
if isinstance(child, ast.Str)
111111
]
112112
# JoinedStr consists of list of Constant and FormattedValue
113113
# instances. Let's perform one test for the whole string
114114
# and abandon all parts except the first one to raise one
115115
# failed test instead of many for the same SQL statement.
116116
if substrings and node == substrings[0]:
117-
statement = "".join([str(child.value) for child in substrings])
117+
statement = "".join([str(child.s) for child in substrings])
118118
wrapper = node._bandit_parent._bandit_parent
119119

120120
if isinstance(wrapper, ast.Call): # wrapped in "execute" call?

bandit/plugins/tarfile_unsafe_members.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def is_filter_data(context):
9898
for keyword in context.node.keywords:
9999
if keyword.arg == "filter":
100100
arg = keyword.value
101-
return isinstance(arg, ast.Constant) and arg.value == "data"
101+
return isinstance(arg, ast.Str) and arg.s == "data"
102102

103103

104104
@test.test_id("B202")

0 commit comments

Comments
 (0)