[flake8-bandit] Implement upstream updates for S311, S324 and S605 (#10313)

## Summary

Pick up updates made in latest
[releases](https://github.com/PyCQA/bandit/releases) of `bandit`:
- `S311`: https://github.com/PyCQA/bandit/pull/940 and
https://github.com/PyCQA/bandit/pull/1096
- `S324`: https://github.com/PyCQA/bandit/pull/1018
- `S605`: https://github.com/PyCQA/bandit/pull/1116

## Test Plan

Snapshot tests
This commit is contained in:
Mathieu Kniewallner 2024-03-11 22:07:58 +01:00 committed by GitHub
parent ad84eedc18
commit bc693ea13a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 512 additions and 245 deletions

View file

@ -0,0 +1,22 @@
import os
import random
import a_lib
# OK
random.SystemRandom()
# Errors
random.Random()
random.random()
random.randrange()
random.randint()
random.choice()
random.choices()
random.uniform()
random.triangular()
random.randbytes()
# Unrelated
os.urandom()
a_lib.random()

View file

@ -1,52 +1,47 @@
import crypt
import hashlib import hashlib
from hashlib import new as hashlib_new from hashlib import new as hashlib_new
from hashlib import sha1 as hashlib_sha1 from hashlib import sha1 as hashlib_sha1
# Invalid # Errors
hashlib.new('md5') hashlib.new('md5')
hashlib.new('md4', b'test') hashlib.new('md4', b'test')
hashlib.new(name='md5', data=b'test') hashlib.new(name='md5', data=b'test')
hashlib.new('MD4', data=b'test') hashlib.new('MD4', data=b'test')
hashlib.new('sha1') hashlib.new('sha1')
hashlib.new('sha1', data=b'test') hashlib.new('sha1', data=b'test')
hashlib.new('sha', data=b'test') hashlib.new('sha', data=b'test')
hashlib.new(name='SHA', data=b'test') hashlib.new(name='SHA', data=b'test')
hashlib.sha(data=b'test') hashlib.sha(data=b'test')
hashlib.md5() hashlib.md5()
hashlib_new('sha1') hashlib_new('sha1')
hashlib_sha1('sha1') hashlib_sha1('sha1')
# usedforsecurity arg only available in Python 3.9+ # usedforsecurity arg only available in Python 3.9+
hashlib.new('sha1', usedforsecurity=True) hashlib.new('sha1', usedforsecurity=True)
# Valid crypt.crypt("test", salt=crypt.METHOD_CRYPT)
crypt.crypt("test", salt=crypt.METHOD_MD5)
crypt.crypt("test", salt=crypt.METHOD_BLOWFISH)
crypt.crypt("test", crypt.METHOD_BLOWFISH)
crypt.mksalt(crypt.METHOD_CRYPT)
crypt.mksalt(crypt.METHOD_MD5)
crypt.mksalt(crypt.METHOD_BLOWFISH)
# OK
hashlib.new('sha256') hashlib.new('sha256')
hashlib.new('SHA512') hashlib.new('SHA512')
hashlib.sha256(data=b'test') hashlib.sha256(data=b'test')
# usedforsecurity arg only available in Python 3.9+ # usedforsecurity arg only available in Python 3.9+
hashlib_new(name='sha1', usedforsecurity=False) hashlib_new(name='sha1', usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib_sha1(name='sha1', usedforsecurity=False) hashlib_sha1(name='sha1', usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib.md4(usedforsecurity=False) hashlib.md4(usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib.new(name='sha256', usedforsecurity=False) hashlib.new(name='sha256', usedforsecurity=False)
crypt.crypt("test")
crypt.crypt("test", salt=crypt.METHOD_SHA256)
crypt.crypt("test", salt=crypt.METHOD_SHA512)
crypt.mksalt()
crypt.mksalt(crypt.METHOD_SHA256)
crypt.mksalt(crypt.METHOD_SHA512)

View file

@ -1,4 +1,5 @@
import os import os
import subprocess
import commands import commands
import popen2 import popen2
@ -16,6 +17,8 @@ popen2.Popen3("true")
popen2.Popen4("true") popen2.Popen4("true")
commands.getoutput("true") commands.getoutput("true")
commands.getstatusoutput("true") commands.getstatusoutput("true")
subprocess.getoutput("true")
subprocess.getstatusoutput("true")
# Check command argument looks unsafe. # Check command argument looks unsafe.

View file

@ -48,6 +48,7 @@ mod tests {
#[test_case(Rule::SuspiciousEvalUsage, Path::new("S307.py"))] #[test_case(Rule::SuspiciousEvalUsage, Path::new("S307.py"))]
#[test_case(Rule::SuspiciousMarkSafeUsage, Path::new("S308.py"))] #[test_case(Rule::SuspiciousMarkSafeUsage, Path::new("S308.py"))]
#[test_case(Rule::SuspiciousURLOpenUsage, Path::new("S310.py"))] #[test_case(Rule::SuspiciousURLOpenUsage, Path::new("S310.py"))]
#[test_case(Rule::SuspiciousNonCryptographicRandomUsage, Path::new("S311.py"))]
#[test_case(Rule::SuspiciousTelnetUsage, Path::new("S312.py"))] #[test_case(Rule::SuspiciousTelnetUsage, Path::new("S312.py"))]
#[test_case(Rule::SuspiciousTelnetlibImport, Path::new("S401.py"))] #[test_case(Rule::SuspiciousTelnetlibImport, Path::new("S401.py"))]
#[test_case(Rule::SuspiciousFtplibImport, Path::new("S402.py"))] #[test_case(Rule::SuspiciousFtplibImport, Path::new("S402.py"))]

View file

@ -9,7 +9,8 @@ use crate::checkers::ast::Checker;
use super::super::helpers::string_literal; use super::super::helpers::string_literal;
/// ## What it does /// ## What it does
/// Checks for uses of weak or broken cryptographic hash functions. /// Checks for uses of weak or broken cryptographic hash functions in
/// `hashlib` and `crypt` libraries.
/// ///
/// ## Why is this bad? /// ## Why is this bad?
/// Weak or broken cryptographic hash functions may be susceptible to /// Weak or broken cryptographic hash functions may be susceptible to
@ -43,43 +44,76 @@ use super::super::helpers::string_literal;
/// ///
/// ## References /// ## References
/// - [Python documentation: `hashlib` — Secure hashes and message digests](https://docs.python.org/3/library/hashlib.html) /// - [Python documentation: `hashlib` — Secure hashes and message digests](https://docs.python.org/3/library/hashlib.html)
/// - [Python documentation: `crypt` — Function to check Unix passwords](https://docs.python.org/3/library/crypt.html)
/// - [Common Weakness Enumeration: CWE-327](https://cwe.mitre.org/data/definitions/327.html) /// - [Common Weakness Enumeration: CWE-327](https://cwe.mitre.org/data/definitions/327.html)
/// - [Common Weakness Enumeration: CWE-328](https://cwe.mitre.org/data/definitions/328.html) /// - [Common Weakness Enumeration: CWE-328](https://cwe.mitre.org/data/definitions/328.html)
/// - [Common Weakness Enumeration: CWE-916](https://cwe.mitre.org/data/definitions/916.html) /// - [Common Weakness Enumeration: CWE-916](https://cwe.mitre.org/data/definitions/916.html)
#[violation] #[violation]
pub struct HashlibInsecureHashFunction { pub struct HashlibInsecureHashFunction {
library: String,
string: String, string: String,
} }
impl Violation for HashlibInsecureHashFunction { impl Violation for HashlibInsecureHashFunction {
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String { fn message(&self) -> String {
let HashlibInsecureHashFunction { string } = self; let HashlibInsecureHashFunction { library, string } = self;
format!("Probable use of insecure hash functions in `hashlib`: `{string}`") format!("Probable use of insecure hash functions in `{library}`: `{string}`")
} }
} }
/// S324 /// S324
pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast::ExprCall) { pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast::ExprCall) {
if let Some(hashlib_call) = checker if let Some(weak_hash_call) = checker
.semantic() .semantic()
.resolve_qualified_name(&call.func) .resolve_qualified_name(&call.func)
.and_then(|qualified_name| match qualified_name.segments() { .and_then(|qualified_name| match qualified_name.segments() {
["hashlib", "new"] => Some(HashlibCall::New), ["hashlib", "new"] => Some(WeakHashCall::Hashlib {
["hashlib", "md4"] => Some(HashlibCall::WeakHash("md4")), call: HashlibCall::New,
["hashlib", "md5"] => Some(HashlibCall::WeakHash("md5")), }),
["hashlib", "sha"] => Some(HashlibCall::WeakHash("sha")), ["hashlib", "md4"] => Some(WeakHashCall::Hashlib {
["hashlib", "sha1"] => Some(HashlibCall::WeakHash("sha1")), call: HashlibCall::WeakHash("md4"),
}),
["hashlib", "md5"] => Some(WeakHashCall::Hashlib {
call: HashlibCall::WeakHash("md5"),
}),
["hashlib", "sha"] => Some(WeakHashCall::Hashlib {
call: HashlibCall::WeakHash("sha"),
}),
["hashlib", "sha1"] => Some(WeakHashCall::Hashlib {
call: HashlibCall::WeakHash("sha1"),
}),
["crypt", "crypt" | "mksalt"] => Some(WeakHashCall::Crypt),
_ => None, _ => None,
}) })
{ {
match weak_hash_call {
WeakHashCall::Hashlib { call: hashlib_call } => {
detect_insecure_hashlib_calls(checker, call, hashlib_call);
}
WeakHashCall::Crypt => detect_insecure_crypt_calls(checker, call),
}
}
}
fn detect_insecure_hashlib_calls(
checker: &mut Checker,
call: &ast::ExprCall,
hashlib_call: HashlibCall,
) {
if !is_used_for_security(&call.arguments) { if !is_used_for_security(&call.arguments) {
return; return;
} }
match hashlib_call { match hashlib_call {
HashlibCall::New => { HashlibCall::New => {
if let Some(name_arg) = call.arguments.find_argument("name", 0) { let Some(name_arg) = call.arguments.find_argument("name", 0) else {
if let Some(hash_func_name) = string_literal(name_arg) { return;
};
let Some(hash_func_name) = string_literal(name_arg) else {
return;
};
// `hashlib.new` accepts both lowercase and uppercase names for hash // `hashlib.new` accepts both lowercase and uppercase names for hash
// functions. // functions.
if matches!( if matches!(
@ -88,23 +122,56 @@ pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast:
) { ) {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
HashlibInsecureHashFunction { HashlibInsecureHashFunction {
library: "hashlib".to_string(),
string: hash_func_name.to_string(), string: hash_func_name.to_string(),
}, },
name_arg.range(), name_arg.range(),
)); ));
} }
} }
}
}
HashlibCall::WeakHash(func_name) => { HashlibCall::WeakHash(func_name) => {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
HashlibInsecureHashFunction { HashlibInsecureHashFunction {
library: "hashlib".to_string(),
string: (*func_name).to_string(), string: (*func_name).to_string(),
}, },
call.func.range(), call.func.range(),
)); ));
} }
} }
}
fn detect_insecure_crypt_calls(checker: &mut Checker, call: &ast::ExprCall) {
let Some(method) = checker
.semantic()
.resolve_qualified_name(&call.func)
.and_then(|qualified_name| match qualified_name.segments() {
["crypt", "crypt"] => Some(("salt", 1)),
["crypt", "mksalt"] => Some(("method", 0)),
_ => None,
})
.and_then(|(argument_name, position)| {
call.arguments.find_argument(argument_name, position)
})
else {
return;
};
let Some(qualified_name) = checker.semantic().resolve_qualified_name(method) else {
return;
};
if matches!(
qualified_name.segments(),
["crypt", "METHOD_CRYPT" | "METHOD_MD5" | "METHOD_BLOWFISH"]
) {
checker.diagnostics.push(Diagnostic::new(
HashlibInsecureHashFunction {
library: "crypt".to_string(),
string: qualified_name.to_string(),
},
method.range(),
));
} }
} }
@ -114,7 +181,13 @@ fn is_used_for_security(arguments: &Arguments) -> bool {
.map_or(true, |keyword| !is_const_false(&keyword.value)) .map_or(true, |keyword| !is_const_false(&keyword.value))
} }
#[derive(Debug)] #[derive(Debug, Copy, Clone)]
enum WeakHashCall {
Hashlib { call: HashlibCall },
Crypt,
}
#[derive(Debug, Copy, Clone)]
enum HashlibCall { enum HashlibCall {
New, New,
WeakHash(&'static str), WeakHash(&'static str),

View file

@ -433,6 +433,7 @@ fn get_call_kind(func: &Expr, semantic: &SemanticModel) -> Option<CallKind> {
"Popen" | "call" | "check_call" | "check_output" | "run" => { "Popen" | "call" | "check_call" | "check_output" | "run" => {
Some(CallKind::Subprocess) Some(CallKind::Subprocess)
} }
"getoutput" | "getstatusoutput" => Some(CallKind::Shell),
_ => None, _ => None,
}, },
"popen2" => match submodule { "popen2" => match submodule {

View file

@ -867,7 +867,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, call: &ExprCall) {
["urllib", "request", "URLopener" | "FancyURLopener"] | ["urllib", "request", "URLopener" | "FancyURLopener"] |
["six", "moves", "urllib", "request", "URLopener" | "FancyURLopener"] => Some(SuspiciousURLOpenUsage.into()), ["six", "moves", "urllib", "request", "URLopener" | "FancyURLopener"] => Some(SuspiciousURLOpenUsage.into()),
// NonCryptographicRandom // NonCryptographicRandom
["random", "random" | "randrange" | "randint" | "choice" | "choices" | "uniform" | "triangular"] => Some(SuspiciousNonCryptographicRandomUsage.into()), ["random", "Random" | "random" | "randrange" | "randint" | "choice" | "choices" | "uniform" | "triangular" | "randbytes"] => Some(SuspiciousNonCryptographicRandomUsage.into()),
// UnverifiedContext // UnverifiedContext
["ssl", "_create_unverified_context"] => Some(SuspiciousUnverifiedContextUsage.into()), ["ssl", "_create_unverified_context"] => Some(SuspiciousUnverifiedContextUsage.into()),
// XMLCElementTree // XMLCElementTree

View file

@ -0,0 +1,90 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S311.py:10:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
9 | # Errors
10 | random.Random()
| ^^^^^^^^^^^^^^^ S311
11 | random.random()
12 | random.randrange()
|
S311.py:11:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
9 | # Errors
10 | random.Random()
11 | random.random()
| ^^^^^^^^^^^^^^^ S311
12 | random.randrange()
13 | random.randint()
|
S311.py:12:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
10 | random.Random()
11 | random.random()
12 | random.randrange()
| ^^^^^^^^^^^^^^^^^^ S311
13 | random.randint()
14 | random.choice()
|
S311.py:13:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
11 | random.random()
12 | random.randrange()
13 | random.randint()
| ^^^^^^^^^^^^^^^^ S311
14 | random.choice()
15 | random.choices()
|
S311.py:14:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
12 | random.randrange()
13 | random.randint()
14 | random.choice()
| ^^^^^^^^^^^^^^^ S311
15 | random.choices()
16 | random.uniform()
|
S311.py:15:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
13 | random.randint()
14 | random.choice()
15 | random.choices()
| ^^^^^^^^^^^^^^^^ S311
16 | random.uniform()
17 | random.triangular()
|
S311.py:16:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
14 | random.choice()
15 | random.choices()
16 | random.uniform()
| ^^^^^^^^^^^^^^^^ S311
17 | random.triangular()
18 | random.randbytes()
|
S311.py:17:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
15 | random.choices()
16 | random.uniform()
17 | random.triangular()
| ^^^^^^^^^^^^^^^^^^^ S311
18 | random.randbytes()
|
S311.py:18:1: S311 Standard pseudo-random generators are not suitable for cryptographic purposes
|
16 | random.uniform()
17 | random.triangular()
18 | random.randbytes()
| ^^^^^^^^^^^^^^^^^^ S311
19 |
20 | # Unrelated
|

View file

@ -3,131 +3,195 @@ source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
--- ---
S324.py:7:13: S324 Probable use of insecure hash functions in `hashlib`: `md5` S324.py:7:13: S324 Probable use of insecure hash functions in `hashlib`: `md5`
| |
5 | # Invalid 6 | # Errors
6 |
7 | hashlib.new('md5') 7 | hashlib.new('md5')
| ^^^^^ S324 | ^^^^^ S324
8 | 8 | hashlib.new('md4', b'test')
9 | hashlib.new('md4', b'test') 9 | hashlib.new(name='md5', data=b'test')
| |
S324.py:9:13: S324 Probable use of insecure hash functions in `hashlib`: `md4` S324.py:8:13: S324 Probable use of insecure hash functions in `hashlib`: `md4`
|
6 | # Errors
7 | hashlib.new('md5')
8 | hashlib.new('md4', b'test')
| ^^^^^ S324
9 | hashlib.new(name='md5', data=b'test')
10 | hashlib.new('MD4', data=b'test')
|
S324.py:9:18: S324 Probable use of insecure hash functions in `hashlib`: `md5`
| |
7 | hashlib.new('md5') 7 | hashlib.new('md5')
8 | 8 | hashlib.new('md4', b'test')
9 | hashlib.new('md4', b'test') 9 | hashlib.new(name='md5', data=b'test')
| ^^^^^ S324 | ^^^^^ S324
10 | 10 | hashlib.new('MD4', data=b'test')
11 | hashlib.new(name='md5', data=b'test') 11 | hashlib.new('sha1')
| |
S324.py:11:18: S324 Probable use of insecure hash functions in `hashlib`: `md5` S324.py:10:13: S324 Probable use of insecure hash functions in `hashlib`: `MD4`
| |
9 | hashlib.new('md4', b'test') 8 | hashlib.new('md4', b'test')
10 | 9 | hashlib.new(name='md5', data=b'test')
11 | hashlib.new(name='md5', data=b'test') 10 | hashlib.new('MD4', data=b'test')
| ^^^^^ S324 | ^^^^^ S324
12 | 11 | hashlib.new('sha1')
13 | hashlib.new('MD4', data=b'test') 12 | hashlib.new('sha1', data=b'test')
| |
S324.py:13:13: S324 Probable use of insecure hash functions in `hashlib`: `MD4` S324.py:11:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
| |
11 | hashlib.new(name='md5', data=b'test') 9 | hashlib.new(name='md5', data=b'test')
12 | 10 | hashlib.new('MD4', data=b'test')
13 | hashlib.new('MD4', data=b'test') 11 | hashlib.new('sha1')
| ^^^^^ S324
14 |
15 | hashlib.new('sha1')
|
S324.py:15:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
|
13 | hashlib.new('MD4', data=b'test')
14 |
15 | hashlib.new('sha1')
| ^^^^^^ S324 | ^^^^^^ S324
16 | 12 | hashlib.new('sha1', data=b'test')
17 | hashlib.new('sha1', data=b'test') 13 | hashlib.new('sha', data=b'test')
|
S324.py:12:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
|
10 | hashlib.new('MD4', data=b'test')
11 | hashlib.new('sha1')
12 | hashlib.new('sha1', data=b'test')
| ^^^^^^ S324
13 | hashlib.new('sha', data=b'test')
14 | hashlib.new(name='SHA', data=b'test')
|
S324.py:13:13: S324 Probable use of insecure hash functions in `hashlib`: `sha`
|
11 | hashlib.new('sha1')
12 | hashlib.new('sha1', data=b'test')
13 | hashlib.new('sha', data=b'test')
| ^^^^^ S324
14 | hashlib.new(name='SHA', data=b'test')
15 | hashlib.sha(data=b'test')
|
S324.py:14:18: S324 Probable use of insecure hash functions in `hashlib`: `SHA`
|
12 | hashlib.new('sha1', data=b'test')
13 | hashlib.new('sha', data=b'test')
14 | hashlib.new(name='SHA', data=b'test')
| ^^^^^ S324
15 | hashlib.sha(data=b'test')
16 | hashlib.md5()
|
S324.py:15:1: S324 Probable use of insecure hash functions in `hashlib`: `sha`
|
13 | hashlib.new('sha', data=b'test')
14 | hashlib.new(name='SHA', data=b'test')
15 | hashlib.sha(data=b'test')
| ^^^^^^^^^^^ S324
16 | hashlib.md5()
17 | hashlib_new('sha1')
|
S324.py:16:1: S324 Probable use of insecure hash functions in `hashlib`: `md5`
|
14 | hashlib.new(name='SHA', data=b'test')
15 | hashlib.sha(data=b'test')
16 | hashlib.md5()
| ^^^^^^^^^^^ S324
17 | hashlib_new('sha1')
18 | hashlib_sha1('sha1')
| |
S324.py:17:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1` S324.py:17:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
| |
15 | hashlib.new('sha1') 15 | hashlib.sha(data=b'test')
16 | 16 | hashlib.md5()
17 | hashlib.new('sha1', data=b'test') 17 | hashlib_new('sha1')
| ^^^^^^ S324 | ^^^^^^ S324
18 | 18 | hashlib_sha1('sha1')
19 | hashlib.new('sha', data=b'test') 19 | # usedforsecurity arg only available in Python 3.9+
| |
S324.py:19:13: S324 Probable use of insecure hash functions in `hashlib`: `sha` S324.py:18:1: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
| |
17 | hashlib.new('sha1', data=b'test') 16 | hashlib.md5()
18 | 17 | hashlib_new('sha1')
19 | hashlib.new('sha', data=b'test') 18 | hashlib_sha1('sha1')
| ^^^^^ S324
20 |
21 | hashlib.new(name='SHA', data=b'test')
|
S324.py:21:18: S324 Probable use of insecure hash functions in `hashlib`: `SHA`
|
19 | hashlib.new('sha', data=b'test')
20 |
21 | hashlib.new(name='SHA', data=b'test')
| ^^^^^ S324
22 |
23 | hashlib.sha(data=b'test')
|
S324.py:23:1: S324 Probable use of insecure hash functions in `hashlib`: `sha`
|
21 | hashlib.new(name='SHA', data=b'test')
22 |
23 | hashlib.sha(data=b'test')
| ^^^^^^^^^^^ S324
24 |
25 | hashlib.md5()
|
S324.py:25:1: S324 Probable use of insecure hash functions in `hashlib`: `md5`
|
23 | hashlib.sha(data=b'test')
24 |
25 | hashlib.md5()
| ^^^^^^^^^^^ S324
26 |
27 | hashlib_new('sha1')
|
S324.py:27:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
|
25 | hashlib.md5()
26 |
27 | hashlib_new('sha1')
| ^^^^^^ S324
28 |
29 | hashlib_sha1('sha1')
|
S324.py:29:1: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
|
27 | hashlib_new('sha1')
28 |
29 | hashlib_sha1('sha1')
| ^^^^^^^^^^^^ S324 | ^^^^^^^^^^^^ S324
30 | 19 | # usedforsecurity arg only available in Python 3.9+
31 | # usedforsecurity arg only available in Python 3.9+ 20 | hashlib.new('sha1', usedforsecurity=True)
| |
S324.py:32:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1` S324.py:20:13: S324 Probable use of insecure hash functions in `hashlib`: `sha1`
| |
31 | # usedforsecurity arg only available in Python 3.9+ 18 | hashlib_sha1('sha1')
32 | hashlib.new('sha1', usedforsecurity=True) 19 | # usedforsecurity arg only available in Python 3.9+
20 | hashlib.new('sha1', usedforsecurity=True)
| ^^^^^^ S324 | ^^^^^^ S324
33 | 21 |
34 | # Valid 22 | crypt.crypt("test", salt=crypt.METHOD_CRYPT)
| |
S324.py:22:26: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_CRYPT`
|
20 | hashlib.new('sha1', usedforsecurity=True)
21 |
22 | crypt.crypt("test", salt=crypt.METHOD_CRYPT)
| ^^^^^^^^^^^^^^^^^^ S324
23 | crypt.crypt("test", salt=crypt.METHOD_MD5)
24 | crypt.crypt("test", salt=crypt.METHOD_BLOWFISH)
|
S324.py:23:26: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_MD5`
|
22 | crypt.crypt("test", salt=crypt.METHOD_CRYPT)
23 | crypt.crypt("test", salt=crypt.METHOD_MD5)
| ^^^^^^^^^^^^^^^^ S324
24 | crypt.crypt("test", salt=crypt.METHOD_BLOWFISH)
25 | crypt.crypt("test", crypt.METHOD_BLOWFISH)
|
S324.py:24:26: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_BLOWFISH`
|
22 | crypt.crypt("test", salt=crypt.METHOD_CRYPT)
23 | crypt.crypt("test", salt=crypt.METHOD_MD5)
24 | crypt.crypt("test", salt=crypt.METHOD_BLOWFISH)
| ^^^^^^^^^^^^^^^^^^^^^ S324
25 | crypt.crypt("test", crypt.METHOD_BLOWFISH)
|
S324.py:25:21: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_BLOWFISH`
|
23 | crypt.crypt("test", salt=crypt.METHOD_MD5)
24 | crypt.crypt("test", salt=crypt.METHOD_BLOWFISH)
25 | crypt.crypt("test", crypt.METHOD_BLOWFISH)
| ^^^^^^^^^^^^^^^^^^^^^ S324
26 |
27 | crypt.mksalt(crypt.METHOD_CRYPT)
|
S324.py:27:14: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_CRYPT`
|
25 | crypt.crypt("test", crypt.METHOD_BLOWFISH)
26 |
27 | crypt.mksalt(crypt.METHOD_CRYPT)
| ^^^^^^^^^^^^^^^^^^ S324
28 | crypt.mksalt(crypt.METHOD_MD5)
29 | crypt.mksalt(crypt.METHOD_BLOWFISH)
|
S324.py:28:14: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_MD5`
|
27 | crypt.mksalt(crypt.METHOD_CRYPT)
28 | crypt.mksalt(crypt.METHOD_MD5)
| ^^^^^^^^^^^^^^^^ S324
29 | crypt.mksalt(crypt.METHOD_BLOWFISH)
|
S324.py:29:14: S324 Probable use of insecure hash functions in `crypt`: `crypt.METHOD_BLOWFISH`
|
27 | crypt.mksalt(crypt.METHOD_CRYPT)
28 | crypt.mksalt(crypt.METHOD_MD5)
29 | crypt.mksalt(crypt.METHOD_BLOWFISH)
| ^^^^^^^^^^^^^^^^^^^^^ S324
30 |
31 | # OK
|

View file

@ -1,147 +1,165 @@
--- ---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
--- ---
S605.py:7:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:8:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
6 | # Check all shell functions. 7 | # Check all shell functions.
7 | os.system("true") 8 | os.system("true")
| ^^^^^^ S605 | ^^^^^^ S605
8 | os.popen("true") 9 | os.popen("true")
9 | os.popen2("true") 10 | os.popen2("true")
| |
S605.py:8:10: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:9:10: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
6 | # Check all shell functions. 7 | # Check all shell functions.
7 | os.system("true") 8 | os.system("true")
8 | os.popen("true") 9 | os.popen("true")
| ^^^^^^ S605 | ^^^^^^ S605
9 | os.popen2("true") 10 | os.popen2("true")
10 | os.popen3("true") 11 | os.popen3("true")
|
S605.py:9:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
|
7 | os.system("true")
8 | os.popen("true")
9 | os.popen2("true")
| ^^^^^^ S605
10 | os.popen3("true")
11 | os.popen4("true")
| |
S605.py:10:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:10:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
8 | os.popen("true") 8 | os.system("true")
9 | os.popen2("true") 9 | os.popen("true")
10 | os.popen3("true") 10 | os.popen2("true")
| ^^^^^^ S605 | ^^^^^^ S605
11 | os.popen4("true") 11 | os.popen3("true")
12 | popen2.popen2("true") 12 | os.popen4("true")
| |
S605.py:11:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:11:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
9 | os.popen2("true") 9 | os.popen("true")
10 | os.popen3("true") 10 | os.popen2("true")
11 | os.popen4("true") 11 | os.popen3("true")
| ^^^^^^ S605 | ^^^^^^ S605
12 | popen2.popen2("true") 12 | os.popen4("true")
13 | popen2.popen3("true") 13 | popen2.popen2("true")
| |
S605.py:12:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:12:11: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
10 | os.popen3("true") 10 | os.popen2("true")
11 | os.popen4("true") 11 | os.popen3("true")
12 | popen2.popen2("true") 12 | os.popen4("true")
| ^^^^^^ S605 | ^^^^^^ S605
13 | popen2.popen3("true") 13 | popen2.popen2("true")
14 | popen2.popen4("true") 14 | popen2.popen3("true")
| |
S605.py:13:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:13:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
11 | os.popen4("true") 11 | os.popen3("true")
12 | popen2.popen2("true") 12 | os.popen4("true")
13 | popen2.popen3("true") 13 | popen2.popen2("true")
| ^^^^^^ S605 | ^^^^^^ S605
14 | popen2.popen4("true") 14 | popen2.popen3("true")
15 | popen2.Popen3("true") 15 | popen2.popen4("true")
| |
S605.py:14:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:14:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
12 | popen2.popen2("true") 12 | os.popen4("true")
13 | popen2.popen3("true") 13 | popen2.popen2("true")
14 | popen2.popen4("true") 14 | popen2.popen3("true")
| ^^^^^^ S605 | ^^^^^^ S605
15 | popen2.Popen3("true") 15 | popen2.popen4("true")
16 | popen2.Popen4("true") 16 | popen2.Popen3("true")
| |
S605.py:15:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:15:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
13 | popen2.popen3("true") 13 | popen2.popen2("true")
14 | popen2.popen4("true") 14 | popen2.popen3("true")
15 | popen2.Popen3("true") 15 | popen2.popen4("true")
| ^^^^^^ S605 | ^^^^^^ S605
16 | popen2.Popen4("true") 16 | popen2.Popen3("true")
17 | commands.getoutput("true") 17 | popen2.Popen4("true")
| |
S605.py:16:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:16:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
14 | popen2.popen4("true") 14 | popen2.popen3("true")
15 | popen2.Popen3("true") 15 | popen2.popen4("true")
16 | popen2.Popen4("true") 16 | popen2.Popen3("true")
| ^^^^^^ S605 | ^^^^^^ S605
17 | commands.getoutput("true") 17 | popen2.Popen4("true")
18 | commands.getstatusoutput("true") 18 | commands.getoutput("true")
| |
S605.py:17:20: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:17:15: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
15 | popen2.Popen3("true") 15 | popen2.popen4("true")
16 | popen2.Popen4("true") 16 | popen2.Popen3("true")
17 | commands.getoutput("true") 17 | popen2.Popen4("true")
| ^^^^^^ S605 | ^^^^^^ S605
18 | commands.getstatusoutput("true") 18 | commands.getoutput("true")
19 | commands.getstatusoutput("true")
| |
S605.py:18:26: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell` S605.py:18:20: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
| |
16 | popen2.Popen4("true") 16 | popen2.Popen3("true")
17 | commands.getoutput("true") 17 | popen2.Popen4("true")
18 | commands.getstatusoutput("true") 18 | commands.getoutput("true")
| ^^^^^^ S605
19 | commands.getstatusoutput("true")
20 | subprocess.getoutput("true")
|
S605.py:19:26: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
|
17 | popen2.Popen4("true")
18 | commands.getoutput("true")
19 | commands.getstatusoutput("true")
| ^^^^^^ S605
20 | subprocess.getoutput("true")
21 | subprocess.getstatusoutput("true")
|
S605.py:20:22: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
|
18 | commands.getoutput("true")
19 | commands.getstatusoutput("true")
20 | subprocess.getoutput("true")
| ^^^^^^ S605
21 | subprocess.getstatusoutput("true")
|
S605.py:21:28: S605 Starting a process with a shell: seems safe, but may be changed in the future; consider rewriting without `shell`
|
19 | commands.getstatusoutput("true")
20 | subprocess.getoutput("true")
21 | subprocess.getstatusoutput("true")
| ^^^^^^ S605 | ^^^^^^ S605
| |
S605.py:23:11: S605 Starting a process with a shell, possible injection detected S605.py:26:11: S605 Starting a process with a shell, possible injection detected
| |
21 | # Check command argument looks unsafe. 24 | # Check command argument looks unsafe.
22 | var_string = "true" 25 | var_string = "true"
23 | os.system(var_string) 26 | os.system(var_string)
| ^^^^^^^^^^ S605 | ^^^^^^^^^^ S605
24 | os.system([var_string]) 27 | os.system([var_string])
25 | os.system([var_string, ""]) 28 | os.system([var_string, ""])
| |
S605.py:24:11: S605 Starting a process with a shell, possible injection detected S605.py:27:11: S605 Starting a process with a shell, possible injection detected
| |
22 | var_string = "true" 25 | var_string = "true"
23 | os.system(var_string) 26 | os.system(var_string)
24 | os.system([var_string]) 27 | os.system([var_string])
| ^^^^^^^^^^^^ S605 | ^^^^^^^^^^^^ S605
25 | os.system([var_string, ""]) 28 | os.system([var_string, ""])
| |
S605.py:25:11: S605 Starting a process with a shell, possible injection detected S605.py:28:11: S605 Starting a process with a shell, possible injection detected
| |
23 | os.system(var_string) 26 | os.system(var_string)
24 | os.system([var_string]) 27 | os.system([var_string])
25 | os.system([var_string, ""]) 28 | os.system([var_string, ""])
| ^^^^^^^^^^^^^^^^ S605 | ^^^^^^^^^^^^^^^^ S605
| |