diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_bandit/S505.py b/crates/ruff_linter/resources/test/fixtures/flake8_bandit/S505.py index 71262866cbd93e..a21b28c9077f8b 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_bandit/S505.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_bandit/S505.py @@ -7,11 +7,12 @@ from Cryptodome.PublicKey import DSA as pycryptodomex_dsa from Cryptodome.PublicKey import RSA as pycryptodomex_rsa - -# Okay +# OK dsa.generate_private_key(key_size=2048, backend=backends.default_backend()) ec.generate_private_key(curve=ec.SECP384R1, backend=backends.default_backend()) -rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=backends.default_backend()) +rsa.generate_private_key( + public_exponent=65537, key_size=2048, backend=backends.default_backend() +) pycrypto_dsa.generate(bits=2048) pycrypto_rsa.generate(bits=2048) pycryptodomex_dsa.generate(bits=2048) @@ -23,11 +24,13 @@ pycrypto_rsa.generate(2048) pycryptodomex_dsa.generate(2048) pycryptodomex_rsa.generate(2048) -# -# # Errors + +# Errors dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) -rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) +rsa.generate_private_key( + public_exponent=65537, key_size=2047, backend=backends.default_backend() +) pycrypto_dsa.generate(bits=2047) pycrypto_rsa.generate(bits=2047) pycryptodomex_dsa.generate(bits=2047) @@ -40,8 +43,12 @@ pycryptodomex_dsa.generate(2047) pycryptodomex_rsa.generate(2047) -# Don't crash when the size is variable -rsa.generate_private_key(public_exponent=65537, key_size=some_key_size, backend=backends.default_backend()) +# Don't crash when the size is variable. +rsa.generate_private_key( + public_exponent=65537, key_size=some_key_size, backend=backends.default_backend() +) -# Can't reliably know which curve was passed, in some cases like below -ec.generate_private_key(curve=curves[self.curve]['create'](self.size), backend=backends.default_backend()) +# Can't reliably know which curve was passed, in some cases like below. +ec.generate_private_key( + curve=curves[self.curve]["create"](self.size), backend=backends.default_backend() +) diff --git a/crates/ruff_linter/src/rules/flake8_bandit/rules/weak_cryptographic_key.rs b/crates/ruff_linter/src/rules/flake8_bandit/rules/weak_cryptographic_key.rs index eb96510ea24239..6fde8c1fb53b9b 100644 --- a/crates/ruff_linter/src/rules/flake8_bandit/rules/weak_cryptographic_key.rs +++ b/crates/ruff_linter/src/rules/flake8_bandit/rules/weak_cryptographic_key.rs @@ -1,17 +1,12 @@ -use once_cell::sync::Lazy; +use std::fmt::{Display, Formatter}; + use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::{self as ast, Constant, Expr, ExprAttribute, ExprCall}; use ruff_text_size::{Ranged, TextRange}; -use rustc_hash::FxHashSet; -use similar::DiffableStr; -use std::fmt::{Display, Formatter}; use crate::checkers::ast::Checker; -static VULNERABLE_ELLIPTIC_CURVE_KEYS: Lazy> = - Lazy::new(|| FxHashSet::from_iter(["SECP192R1", "SECT163K1", "SECT163R2"])); - #[derive(Debug, PartialEq, Eq)] enum CryptographicKey { Dsa { key_size: u16 }, @@ -30,7 +25,9 @@ impl CryptographicKey { fn is_vulnerable(&self) -> bool { match self { Self::Dsa { key_size } | Self::Rsa { key_size } => key_size < &self.minimum_key_size(), - Self::Ec { algorithm } => VULNERABLE_ELLIPTIC_CURVE_KEYS.contains(algorithm.as_str()), + Self::Ec { algorithm } => { + matches!(algorithm.as_str(), "SECP192R1" | "SECT163K1" | "SECT163R2") + } } } } @@ -111,16 +108,16 @@ fn extract_cryptographic_key( .resolve_call_path(&call.func) .and_then(|call_path| match call_path.as_slice() { ["cryptography", "hazmat", "primitives", "asymmetric", function, "generate_private_key"] => { - return match function.as_str() { - Some("dsa") => { + return match *function { + "dsa" => { let Some((key_size, range)) = extract_int_argument(call, "key_size", 0) else {return None}; return Some((CryptographicKey::Dsa { key_size }, range)); }, - Some("rsa") => { + "rsa" => { let Some((key_size, range)) = extract_int_argument(call, "key_size", 1) else {return None}; return Some((CryptographicKey::Rsa { key_size }, range)); }, - Some("ec") => { + "ec" => { let Some(argument) = call.arguments.find_argument("curve", 0) else { return None }; let Expr::Attribute(ExprAttribute { attr, value, .. }) = argument else { return None }; @@ -137,12 +134,12 @@ fn extract_cryptographic_key( }; }, ["Crypto" | "Cryptodome", "PublicKey", function, "generate"] => { - return match function.as_str() { - Some("DSA") => { + return match *function { + "DSA" => { let Some((key_size, range)) = extract_int_argument(call, "bits", 0) else {return None}; return Some((CryptographicKey::Dsa { key_size }, range)); }, - Some("RSA") => { + "RSA" => { let Some((key_size, range)) = extract_int_argument(call, "bits", 0) else {return None}; return Some((CryptographicKey::Dsa { key_size }, range)); }, @@ -155,10 +152,6 @@ fn extract_cryptographic_key( /// S505 pub(crate) fn weak_cryptographic_key(checker: &mut Checker, call: &ExprCall) { - let Expr::Attribute(_) = call.func.as_ref() else { - return; - }; - let Some((cryptographic_key, range)) = extract_cryptographic_key(checker, call) else { return; }; diff --git a/crates/ruff_linter/src/rules/flake8_bandit/snapshots/ruff_linter__rules__flake8_bandit__tests__S505_S505.py.snap b/crates/ruff_linter/src/rules/flake8_bandit/snapshots/ruff_linter__rules__flake8_bandit__tests__S505_S505.py.snap index b5d55bcd5614d7..bc14a8556f74ae 100644 --- a/crates/ruff_linter/src/rules/flake8_bandit/snapshots/ruff_linter__rules__flake8_bandit__tests__S505_S505.py.snap +++ b/crates/ruff_linter/src/rules/flake8_bandit/snapshots/ruff_linter__rules__flake8_bandit__tests__S505_S505.py.snap @@ -1,143 +1,142 @@ --- source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs --- -S505.py:28:35: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:29:35: S505 DSA key sizes below 2048 bits are considered breakable | -26 | # -27 | # # Errors -28 | dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) +28 | # Errors +29 | dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) | ^^^^ S505 -29 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) -30 | rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) +30 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) +31 | rsa.generate_private_key( | -S505.py:29:31: S505 EC key sizes below 224 bits are considered breakable +S505.py:30:31: S505 EC key sizes below 224 bits are considered breakable | -27 | # # Errors -28 | dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) -29 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) +28 | # Errors +29 | dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) +30 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) | ^^^^^^^^^^^^ S505 -30 | rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) -31 | pycrypto_dsa.generate(bits=2047) +31 | rsa.generate_private_key( +32 | public_exponent=65537, key_size=2047, backend=backends.default_backend() | -S505.py:30:58: S505 RSA key sizes below 2048 bits are considered breakable +S505.py:32:37: S505 RSA key sizes below 2048 bits are considered breakable | -28 | dsa.generate_private_key(key_size=2047, backend=backends.default_backend()) -29 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) -30 | rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) - | ^^^^ S505 -31 | pycrypto_dsa.generate(bits=2047) -32 | pycrypto_rsa.generate(bits=2047) +30 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) +31 | rsa.generate_private_key( +32 | public_exponent=65537, key_size=2047, backend=backends.default_backend() + | ^^^^ S505 +33 | ) +34 | pycrypto_dsa.generate(bits=2047) | -S505.py:31:28: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:34:28: S505 DSA key sizes below 2048 bits are considered breakable | -29 | ec.generate_private_key(curve=ec.SECT163R2, backend=backends.default_backend()) -30 | rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) -31 | pycrypto_dsa.generate(bits=2047) +32 | public_exponent=65537, key_size=2047, backend=backends.default_backend() +33 | ) +34 | pycrypto_dsa.generate(bits=2047) | ^^^^ S505 -32 | pycrypto_rsa.generate(bits=2047) -33 | pycryptodomex_dsa.generate(bits=2047) +35 | pycrypto_rsa.generate(bits=2047) +36 | pycryptodomex_dsa.generate(bits=2047) | -S505.py:32:28: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:35:28: S505 DSA key sizes below 2048 bits are considered breakable | -30 | rsa.generate_private_key(public_exponent=65537, key_size=2047, backend=backends.default_backend()) -31 | pycrypto_dsa.generate(bits=2047) -32 | pycrypto_rsa.generate(bits=2047) +33 | ) +34 | pycrypto_dsa.generate(bits=2047) +35 | pycrypto_rsa.generate(bits=2047) | ^^^^ S505 -33 | pycryptodomex_dsa.generate(bits=2047) -34 | pycryptodomex_rsa.generate(bits=2047) +36 | pycryptodomex_dsa.generate(bits=2047) +37 | pycryptodomex_rsa.generate(bits=2047) | -S505.py:33:33: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:36:33: S505 DSA key sizes below 2048 bits are considered breakable | -31 | pycrypto_dsa.generate(bits=2047) -32 | pycrypto_rsa.generate(bits=2047) -33 | pycryptodomex_dsa.generate(bits=2047) +34 | pycrypto_dsa.generate(bits=2047) +35 | pycrypto_rsa.generate(bits=2047) +36 | pycryptodomex_dsa.generate(bits=2047) | ^^^^ S505 -34 | pycryptodomex_rsa.generate(bits=2047) -35 | dsa.generate_private_key(2047, backends.default_backend()) +37 | pycryptodomex_rsa.generate(bits=2047) +38 | dsa.generate_private_key(2047, backends.default_backend()) | -S505.py:34:33: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:37:33: S505 DSA key sizes below 2048 bits are considered breakable | -32 | pycrypto_rsa.generate(bits=2047) -33 | pycryptodomex_dsa.generate(bits=2047) -34 | pycryptodomex_rsa.generate(bits=2047) +35 | pycrypto_rsa.generate(bits=2047) +36 | pycryptodomex_dsa.generate(bits=2047) +37 | pycryptodomex_rsa.generate(bits=2047) | ^^^^ S505 -35 | dsa.generate_private_key(2047, backends.default_backend()) -36 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) +38 | dsa.generate_private_key(2047, backends.default_backend()) +39 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) | -S505.py:35:26: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:38:26: S505 DSA key sizes below 2048 bits are considered breakable | -33 | pycryptodomex_dsa.generate(bits=2047) -34 | pycryptodomex_rsa.generate(bits=2047) -35 | dsa.generate_private_key(2047, backends.default_backend()) +36 | pycryptodomex_dsa.generate(bits=2047) +37 | pycryptodomex_rsa.generate(bits=2047) +38 | dsa.generate_private_key(2047, backends.default_backend()) | ^^^^ S505 -36 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) -37 | rsa.generate_private_key(3, 2047, backends.default_backend()) +39 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) +40 | rsa.generate_private_key(3, 2047, backends.default_backend()) | -S505.py:36:25: S505 EC key sizes below 224 bits are considered breakable +S505.py:39:25: S505 EC key sizes below 224 bits are considered breakable | -34 | pycryptodomex_rsa.generate(bits=2047) -35 | dsa.generate_private_key(2047, backends.default_backend()) -36 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) +37 | pycryptodomex_rsa.generate(bits=2047) +38 | dsa.generate_private_key(2047, backends.default_backend()) +39 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) | ^^^^^^^^^^^^ S505 -37 | rsa.generate_private_key(3, 2047, backends.default_backend()) -38 | pycrypto_dsa.generate(2047) +40 | rsa.generate_private_key(3, 2047, backends.default_backend()) +41 | pycrypto_dsa.generate(2047) | -S505.py:37:29: S505 RSA key sizes below 2048 bits are considered breakable +S505.py:40:29: S505 RSA key sizes below 2048 bits are considered breakable | -35 | dsa.generate_private_key(2047, backends.default_backend()) -36 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) -37 | rsa.generate_private_key(3, 2047, backends.default_backend()) +38 | dsa.generate_private_key(2047, backends.default_backend()) +39 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) +40 | rsa.generate_private_key(3, 2047, backends.default_backend()) | ^^^^ S505 -38 | pycrypto_dsa.generate(2047) -39 | pycrypto_rsa.generate(2047) +41 | pycrypto_dsa.generate(2047) +42 | pycrypto_rsa.generate(2047) | -S505.py:38:23: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:41:23: S505 DSA key sizes below 2048 bits are considered breakable | -36 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) -37 | rsa.generate_private_key(3, 2047, backends.default_backend()) -38 | pycrypto_dsa.generate(2047) +39 | ec.generate_private_key(ec.SECT163R2, backends.default_backend()) +40 | rsa.generate_private_key(3, 2047, backends.default_backend()) +41 | pycrypto_dsa.generate(2047) | ^^^^ S505 -39 | pycrypto_rsa.generate(2047) -40 | pycryptodomex_dsa.generate(2047) +42 | pycrypto_rsa.generate(2047) +43 | pycryptodomex_dsa.generate(2047) | -S505.py:39:23: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:42:23: S505 DSA key sizes below 2048 bits are considered breakable | -37 | rsa.generate_private_key(3, 2047, backends.default_backend()) -38 | pycrypto_dsa.generate(2047) -39 | pycrypto_rsa.generate(2047) +40 | rsa.generate_private_key(3, 2047, backends.default_backend()) +41 | pycrypto_dsa.generate(2047) +42 | pycrypto_rsa.generate(2047) | ^^^^ S505 -40 | pycryptodomex_dsa.generate(2047) -41 | pycryptodomex_rsa.generate(2047) +43 | pycryptodomex_dsa.generate(2047) +44 | pycryptodomex_rsa.generate(2047) | -S505.py:40:28: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:43:28: S505 DSA key sizes below 2048 bits are considered breakable | -38 | pycrypto_dsa.generate(2047) -39 | pycrypto_rsa.generate(2047) -40 | pycryptodomex_dsa.generate(2047) +41 | pycrypto_dsa.generate(2047) +42 | pycrypto_rsa.generate(2047) +43 | pycryptodomex_dsa.generate(2047) | ^^^^ S505 -41 | pycryptodomex_rsa.generate(2047) +44 | pycryptodomex_rsa.generate(2047) | -S505.py:41:28: S505 DSA key sizes below 2048 bits are considered breakable +S505.py:44:28: S505 DSA key sizes below 2048 bits are considered breakable | -39 | pycrypto_rsa.generate(2047) -40 | pycryptodomex_dsa.generate(2047) -41 | pycryptodomex_rsa.generate(2047) +42 | pycrypto_rsa.generate(2047) +43 | pycryptodomex_dsa.generate(2047) +44 | pycryptodomex_rsa.generate(2047) | ^^^^ S505 -42 | -43 | # Don't crash when the size is variable +45 | +46 | # Don't crash when the size is variable. |