From 7705ba2798e9c565f3dc5104829491cf0e4d5a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Rami=CC=81rez=20Mondrago=CC=81n?= Date: Wed, 4 Jan 2023 15:12:29 -0600 Subject: [PATCH] Implement flake8-bandit rule `S108` --- README.md | 39 +++++++++ flake8_to_ruff/src/converter.rs | 7 ++ resources/test/fixtures/flake8_bandit/S108.py | 16 ++++ ruff.schema.json | 38 +++++++++ src/checkers/ast.rs | 9 ++ src/flake8_bandit/checks/hardcoded_tmp_dir.rs | 20 +++++ src/flake8_bandit/checks/mod.rs | 2 + src/flake8_bandit/mod.rs | 51 +++++++++--- src/flake8_bandit/settings.rs | 83 +++++++++++++++++++ ... => ruff__flake8_bandit__tests__S101.snap} | 0 ... => ruff__flake8_bandit__tests__S102.snap} | 0 ... => ruff__flake8_bandit__tests__S103.snap} | 0 ... => ruff__flake8_bandit__tests__S104.snap} | 0 ... => ruff__flake8_bandit__tests__S105.snap} | 0 ... => ruff__flake8_bandit__tests__S106.snap} | 0 ... => ruff__flake8_bandit__tests__S107.snap} | 0 ...f__flake8_bandit__tests__S108_default.snap | 35 ++++++++ ...ff__flake8_bandit__tests__S108_extend.snap | 45 ++++++++++ ...__flake8_bandit__tests__S108_override.snap | 15 ++++ src/registry.rs | 11 +++ src/registry_gen.rs | 7 ++ src/settings/configuration.rs | 5 +- src/settings/mod.rs | 10 ++- src/settings/options.rs | 5 +- src/settings/pyproject.rs | 8 +- 25 files changed, 391 insertions(+), 15 deletions(-) create mode 100644 resources/test/fixtures/flake8_bandit/S108.py create mode 100644 src/flake8_bandit/checks/hardcoded_tmp_dir.rs create mode 100644 src/flake8_bandit/settings.rs rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S101_S101.py.snap => ruff__flake8_bandit__tests__S101.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S102_S102.py.snap => ruff__flake8_bandit__tests__S102.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S103_S103.py.snap => ruff__flake8_bandit__tests__S103.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S104_S104.py.snap => ruff__flake8_bandit__tests__S104.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S105_S105.py.snap => ruff__flake8_bandit__tests__S105.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S106_S106.py.snap => ruff__flake8_bandit__tests__S106.snap} (100%) rename src/flake8_bandit/snapshots/{ruff__flake8_bandit__tests__S107_S107.py.snap => ruff__flake8_bandit__tests__S107.snap} (100%) create mode 100644 src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_default.snap create mode 100644 src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_extend.snap create mode 100644 src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_override.snap diff --git a/README.md b/README.md index afee94227f6889..f0e53dc2f420aa 100644 --- a/README.md +++ b/README.md @@ -770,6 +770,7 @@ For more, see [flake8-bandit](https://pypi.org/project/flake8-bandit/4.1.1/) on | S105 | HardcodedPasswordString | Possible hardcoded password: `"..."` | | | S106 | HardcodedPasswordFuncArg | Possible hardcoded password: `"..."` | | | S107 | HardcodedPasswordDefault | Possible hardcoded password: `"..."` | | +| S108 | HardcodedTempFile | Probable insecure usage of temp file/directory: `"..."` | | ### flake8-blind-except (BLE) @@ -2361,6 +2362,44 @@ suppress-none-returning = true --- +### `flake8-bandit` + +#### [`hardcoded-tmp-directory`](#hardcoded-tmp-directory) + +List of directories that are considered temporary. + +**Default value**: `["/tmp", "/var/tmp", "/dev/shm"]` + +**Type**: `Vec` + +**Example usage**: + +```toml +[tool.ruff.flake8-bandit] +hardcoded_tmp_directory = ["/foo/bar"] +``` + +--- + +#### [`hardcoded-tmp-directory-extend`](#hardcoded-tmp-directory-extend) + +List of directories that are considered temporary. +These directories are added to the list in +`hardcoded_tmp_directory`. + +**Default value**: `[]` + +**Type**: `Vec` + +**Example usage**: + +```toml +[tool.ruff.flake8-bandit] +extend_hardcoded_tmp_directory = ["/foo/bar"] +``` + +--- + ### `flake8-bugbear` #### [`extend-immutable-calls`](#extend-immutable-calls) diff --git a/flake8_to_ruff/src/converter.rs b/flake8_to_ruff/src/converter.rs index 79b629091e7900..a8c3913d1224c3 100644 --- a/flake8_to_ruff/src/converter.rs +++ b/flake8_to_ruff/src/converter.rs @@ -393,6 +393,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -455,6 +456,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -517,6 +519,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -579,6 +582,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -641,6 +645,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -712,6 +717,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -777,6 +783,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, diff --git a/resources/test/fixtures/flake8_bandit/S108.py b/resources/test/fixtures/flake8_bandit/S108.py new file mode 100644 index 00000000000000..d60b808cb584a1 --- /dev/null +++ b/resources/test/fixtures/flake8_bandit/S108.py @@ -0,0 +1,16 @@ +# ok +with open("/abc/tmp", "w") as f: + f.write("def") + +with open("/tmp/abc", "w") as f: + f.write("def") + +with open("/var/tmp/123", "w") as f: + f.write("def") + +with open("/dev/shm/unit/test", "w") as f: + f.write("def") + +# not ok by config +with open("/foo/bar", "w") as f: + f.write("def") diff --git a/ruff.schema.json b/ruff.schema.json index 8f82f95db52f93..28e6624dd1c429 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -121,6 +121,17 @@ } ] }, + "flake8-bandit": { + "description": "Options for the `flake8-bandit` plugin.", + "anyOf": [ + { + "$ref": "#/definitions/Flake8BanditOptions" + }, + { + "type": "null" + } + ] + }, "flake8-bugbear": { "description": "Options for the `flake8-bugbear` plugin.", "anyOf": [ @@ -915,6 +926,7 @@ "S105", "S106", "S107", + "S108", "SIM", "SIM1", "SIM10", @@ -1082,6 +1094,32 @@ }, "additionalProperties": false }, + "Flake8BanditOptions": { + "type": "object", + "properties": { + "hardcoded-tmp-directory": { + "description": "List of directories that are considered temporary.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "hardcoded-tmp-directory-extend": { + "description": "List of directories that are considered temporary. These directories are added to the list in `hardcoded_tmp_directory`.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + } + }, + "additionalProperties": false + }, "Flake8BugbearOptions": { "type": "object", "properties": { diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index 71f7a1d033ca51..bfc93e70d8f1f2 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -2533,6 +2533,15 @@ where self.add_check(check); } } + if self.settings.enabled.contains(&CheckCode::S108) { + if let Some(check) = flake8_bandit::checks::hardcoded_tmp_dir( + expr, + value, + &mut self.settings.flake8_bandit.all_hardcoded_tmp_directories(), + ) { + self.add_check(check); + } + } if self.settings.enabled.contains(&CheckCode::UP025) { pyupgrade::plugins::rewrite_unicode_literal(self, expr, kind); } diff --git a/src/flake8_bandit/checks/hardcoded_tmp_dir.rs b/src/flake8_bandit/checks/hardcoded_tmp_dir.rs new file mode 100644 index 00000000000000..ba4ddb16d44a06 --- /dev/null +++ b/src/flake8_bandit/checks/hardcoded_tmp_dir.rs @@ -0,0 +1,20 @@ +use rustpython_ast::Expr; + +use crate::ast::types::Range; +use crate::registry::{Check, CheckKind}; + +/// S108 +pub fn hardcoded_tmp_dir<'a>( + expr: &Expr, + value: &str, + prefixes: &mut impl Iterator, +) -> Option { + if prefixes.any(|prefix| value.starts_with(prefix)) { + Some(Check::new( + CheckKind::HardcodedTempFile(value.to_string()), + Range::from_located(expr), + )) + } else { + None + } +} diff --git a/src/flake8_bandit/checks/mod.rs b/src/flake8_bandit/checks/mod.rs index d5189a5c2a82f1..a7777c7a3fbdbd 100644 --- a/src/flake8_bandit/checks/mod.rs +++ b/src/flake8_bandit/checks/mod.rs @@ -7,6 +7,7 @@ pub use hardcoded_password_func_arg::hardcoded_password_func_arg; pub use hardcoded_password_string::{ assign_hardcoded_password_string, compare_to_hardcoded_password_string, }; +pub use hardcoded_tmp_dir::hardcoded_tmp_dir; mod assert_used; mod bad_file_permissions; @@ -15,3 +16,4 @@ mod hardcoded_bind_all_interfaces; mod hardcoded_password_default; mod hardcoded_password_func_arg; mod hardcoded_password_string; +mod hardcoded_tmp_dir; diff --git a/src/flake8_bandit/mod.rs b/src/flake8_bandit/mod.rs index f65b108c0e1f1a..fa35d13aadc205 100644 --- a/src/flake8_bandit/mod.rs +++ b/src/flake8_bandit/mod.rs @@ -1,5 +1,6 @@ pub mod checks; mod helpers; +pub mod settings; #[cfg(test)] mod tests { @@ -8,26 +9,54 @@ mod tests { use anyhow::Result; use test_case::test_case; + use crate::flake8_bandit::settings::Settings; use crate::linter::test_path; use crate::registry::CheckCode; use crate::settings; - #[test_case(CheckCode::S101, Path::new("S101.py"); "S101")] - #[test_case(CheckCode::S102, Path::new("S102.py"); "S102")] - #[test_case(CheckCode::S103, Path::new("S103.py"); "S103")] - #[test_case(CheckCode::S104, Path::new("S104.py"); "S104")] - #[test_case(CheckCode::S105, Path::new("S105.py"); "S105")] - #[test_case(CheckCode::S106, Path::new("S106.py"); "S106")] - #[test_case(CheckCode::S107, Path::new("S107.py"); "S107")] - fn checks(check_code: CheckCode, path: &Path) -> Result<()> { - let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy()); + #[test_case(CheckCode::S101, Path::new("S101.py"), Settings::default(), "S101"; "S101")] + #[test_case(CheckCode::S102, Path::new("S102.py"), Settings::default(), "S102"; "S102")] + #[test_case(CheckCode::S103, Path::new("S103.py"), Settings::default(), "S103"; "S103")] + #[test_case(CheckCode::S104, Path::new("S104.py"), Settings::default(), "S104"; "S104")] + #[test_case(CheckCode::S105, Path::new("S105.py"), Settings::default(), "S105"; "S105")] + #[test_case(CheckCode::S106, Path::new("S106.py"), Settings::default(), "S106"; "S106")] + #[test_case(CheckCode::S107, Path::new("S107.py"), Settings::default(), "S107"; "S107")] + #[test_case(CheckCode::S108, Path::new("S108.py"), Settings::default(), "S108_default"; "S108_0")] + #[test_case( + CheckCode::S108, Path::new("S108.py"), + Settings { + hardcoded_tmp_directory: vec!["/foo".to_string()], + ..Settings::default() + }, + "S108_override"; + "S108_1" + )] + #[test_case( + CheckCode::S108, + Path::new("S108.py"), + Settings { + hardcoded_tmp_directory_extend: vec!["/foo".to_string()], + ..Settings::default() + }, + "S108_extend"; + "S108_2" + )] + fn checks( + check_code: CheckCode, + path: &Path, + plugin_settings: Settings, + label: &str, + ) -> Result<()> { let checks = test_path( Path::new("./resources/test/fixtures/flake8_bandit") .join(path) .as_path(), - &settings::Settings::for_rule(check_code), + &settings::Settings { + flake8_bandit: plugin_settings, + ..settings::Settings::for_rule(check_code) + }, )?; - insta::assert_yaml_snapshot!(snapshot, checks); + insta::assert_yaml_snapshot!(label, checks); Ok(()) } } diff --git a/src/flake8_bandit/settings.rs b/src/flake8_bandit/settings.rs new file mode 100644 index 00000000000000..505ce5c33d1c9e --- /dev/null +++ b/src/flake8_bandit/settings.rs @@ -0,0 +1,83 @@ +//! Settings for the `flake8-bandit` plugin. + +use ruff_macros::ConfigurationOptions; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +fn default_tmp_dirs() -> Vec { + ["/tmp", "/var/tmp", "/dev/shm"] + .map(std::string::ToString::to_string) + .to_vec() +} + +#[derive( + Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema, +)] +#[serde( + deny_unknown_fields, + rename_all = "kebab-case", + rename = "Flake8BanditOptions" +)] +pub struct Options { + #[option( + default = "[\"/tmp\", \"/var/tmp\", \"/dev/shm\"]", + value_type = "Vec", + example = "hardcoded_tmp_directory = [\"/foo/bar\"]" + )] + /// List of directories that are considered temporary. + pub hardcoded_tmp_directory: Option>, + #[option( + default = "[]", + value_type = "Vec", + example = "extend_hardcoded_tmp_directory = [\"/foo/bar\"]" + )] + /// List of directories that are considered temporary. + /// These directories are added to the list in + /// `hardcoded_tmp_directory`. + pub hardcoded_tmp_directory_extend: Option>, +} + +#[derive(Debug, Hash)] +pub struct Settings { + pub hardcoded_tmp_directory: Vec, + pub hardcoded_tmp_directory_extend: Vec, +} + +impl From for Settings { + fn from(options: Options) -> Self { + Self { + hardcoded_tmp_directory: options + .hardcoded_tmp_directory + .unwrap_or_else(default_tmp_dirs), + hardcoded_tmp_directory_extend: options + .hardcoded_tmp_directory_extend + .unwrap_or_default(), + } + } +} +impl From for Options { + fn from(settings: Settings) -> Self { + Self { + hardcoded_tmp_directory: Some(settings.hardcoded_tmp_directory), + hardcoded_tmp_directory_extend: Some(settings.hardcoded_tmp_directory_extend), + } + } +} + +impl Default for Settings { + fn default() -> Self { + Self { + hardcoded_tmp_directory: default_tmp_dirs(), + hardcoded_tmp_directory_extend: Vec::new(), + } + } +} + +impl Settings { + /// Returns an iterator over all directories that are considered temporary. + pub fn all_hardcoded_tmp_directories(&'_ self) -> impl Iterator { + self.hardcoded_tmp_directory + .iter() + .chain(self.hardcoded_tmp_directory_extend.iter()) + } +} diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S101_S101.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S101.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S101_S101.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S101.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S102_S102.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S102.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S102_S102.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S102.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S103_S103.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S103.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S103_S103.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S103.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S104_S104.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S104.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S104_S104.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S104.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S105_S105.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S105.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S105_S105.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S105.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S106_S106.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S106.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S106_S106.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S106.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S107_S107.py.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S107.snap similarity index 100% rename from src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S107_S107.py.snap rename to src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S107.snap diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_default.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_default.snap new file mode 100644 index 00000000000000..cfd8f1c96e86ad --- /dev/null +++ b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_default.snap @@ -0,0 +1,35 @@ +--- +source: src/flake8_bandit/mod.rs +expression: checks +--- +- kind: + HardcodedTempFile: /tmp/abc + location: + row: 5 + column: 10 + end_location: + row: 5 + column: 20 + fix: ~ + parent: ~ +- kind: + HardcodedTempFile: /var/tmp/123 + location: + row: 8 + column: 10 + end_location: + row: 8 + column: 24 + fix: ~ + parent: ~ +- kind: + HardcodedTempFile: /dev/shm/unit/test + location: + row: 11 + column: 10 + end_location: + row: 11 + column: 30 + fix: ~ + parent: ~ + diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_extend.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_extend.snap new file mode 100644 index 00000000000000..5d8bd2338b1524 --- /dev/null +++ b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_extend.snap @@ -0,0 +1,45 @@ +--- +source: src/flake8_bandit/mod.rs +expression: checks +--- +- kind: + HardcodedTempFile: /tmp/abc + location: + row: 5 + column: 10 + end_location: + row: 5 + column: 20 + fix: ~ + parent: ~ +- kind: + HardcodedTempFile: /var/tmp/123 + location: + row: 8 + column: 10 + end_location: + row: 8 + column: 24 + fix: ~ + parent: ~ +- kind: + HardcodedTempFile: /dev/shm/unit/test + location: + row: 11 + column: 10 + end_location: + row: 11 + column: 30 + fix: ~ + parent: ~ +- kind: + HardcodedTempFile: /foo/bar + location: + row: 15 + column: 10 + end_location: + row: 15 + column: 20 + fix: ~ + parent: ~ + diff --git a/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_override.snap b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_override.snap new file mode 100644 index 00000000000000..8f29b55446ca48 --- /dev/null +++ b/src/flake8_bandit/snapshots/ruff__flake8_bandit__tests__S108_override.snap @@ -0,0 +1,15 @@ +--- +source: src/flake8_bandit/mod.rs +expression: checks +--- +- kind: + HardcodedTempFile: /foo/bar + location: + row: 15 + column: 10 + end_location: + row: 15 + column: 20 + fix: ~ + parent: ~ + diff --git a/src/registry.rs b/src/registry.rs index b4cb79540cbe95..43761f78c46a11 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -327,6 +327,7 @@ pub enum CheckCode { S105, S106, S107, + S108, // flake8-boolean-trap FBT001, FBT002, @@ -1060,6 +1061,7 @@ pub enum CheckKind { HardcodedPasswordString(String), HardcodedPasswordFuncArg(String), HardcodedPasswordDefault(String), + HardcodedTempFile(String), // mccabe FunctionIsTooComplex(String, usize), // flake8-boolean-trap @@ -1512,6 +1514,7 @@ impl CheckCode { CheckCode::S105 => CheckKind::HardcodedPasswordString("...".to_string()), CheckCode::S106 => CheckKind::HardcodedPasswordFuncArg("...".to_string()), CheckCode::S107 => CheckKind::HardcodedPasswordDefault("...".to_string()), + CheckCode::S108 => CheckKind::HardcodedTempFile("...".to_string()), // mccabe CheckCode::C901 => CheckKind::FunctionIsTooComplex("...".to_string(), 10), // flake8-boolean-trap @@ -1913,6 +1916,7 @@ impl CheckCode { CheckCode::S105 => CheckCategory::Flake8Bandit, CheckCode::S106 => CheckCategory::Flake8Bandit, CheckCode::S107 => CheckCategory::Flake8Bandit, + CheckCode::S108 => CheckCategory::Flake8Bandit, // flake8-simplify CheckCode::SIM105 => CheckCategory::Flake8Simplify, CheckCode::SIM118 => CheckCategory::Flake8Simplify, @@ -2277,6 +2281,7 @@ impl CheckKind { CheckKind::HardcodedPasswordString(..) => &CheckCode::S105, CheckKind::HardcodedPasswordFuncArg(..) => &CheckCode::S106, CheckKind::HardcodedPasswordDefault(..) => &CheckCode::S107, + CheckKind::HardcodedTempFile(..) => &CheckCode::S108, // mccabe CheckKind::FunctionIsTooComplex(..) => &CheckCode::C901, // flake8-boolean-trap @@ -3210,6 +3215,12 @@ impl CheckKind { string.escape_debug() ) } + CheckKind::HardcodedTempFile(string) => { + format!( + "Probable insecure usage of temp file/directory: `\"{}\"`", + string.escape_debug() + ) + } // flake8-blind-except CheckKind::BlindExcept(name) => format!("Do not catch blind exception: `{name}`"), // mccabe diff --git a/src/registry_gen.rs b/src/registry_gen.rs index 34f113ce9ee1d2..d390b91be3eeae 100644 --- a/src/registry_gen.rs +++ b/src/registry_gen.rs @@ -514,6 +514,7 @@ pub enum CheckCodePrefix { S105, S106, S107, + S108, SIM, SIM1, SIM10, @@ -909,6 +910,7 @@ impl CheckCodePrefix { CheckCode::S105, CheckCode::S106, CheckCode::S107, + CheckCode::S108, CheckCode::FBT001, CheckCode::FBT002, CheckCode::FBT003, @@ -2596,6 +2598,7 @@ impl CheckCodePrefix { CheckCode::S105, CheckCode::S106, CheckCode::S107, + CheckCode::S108, ], CheckCodePrefix::S1 => vec![ CheckCode::S101, @@ -2605,6 +2608,7 @@ impl CheckCodePrefix { CheckCode::S105, CheckCode::S106, CheckCode::S107, + CheckCode::S108, ], CheckCodePrefix::S10 => vec![ CheckCode::S101, @@ -2614,6 +2618,7 @@ impl CheckCodePrefix { CheckCode::S105, CheckCode::S106, CheckCode::S107, + CheckCode::S108, ], CheckCodePrefix::S101 => vec![CheckCode::S101], CheckCodePrefix::S102 => vec![CheckCode::S102], @@ -2622,6 +2627,7 @@ impl CheckCodePrefix { CheckCodePrefix::S105 => vec![CheckCode::S105], CheckCodePrefix::S106 => vec![CheckCode::S106], CheckCodePrefix::S107 => vec![CheckCode::S107], + CheckCodePrefix::S108 => vec![CheckCode::S108], CheckCodePrefix::SIM => vec![ CheckCode::SIM105, CheckCode::SIM118, @@ -3602,6 +3608,7 @@ impl CheckCodePrefix { CheckCodePrefix::S105 => SuffixLength::Three, CheckCodePrefix::S106 => SuffixLength::Three, CheckCodePrefix::S107 => SuffixLength::Three, + CheckCodePrefix::S108 => SuffixLength::Three, CheckCodePrefix::SIM => SuffixLength::Zero, CheckCodePrefix::SIM1 => SuffixLength::One, CheckCodePrefix::SIM10 => SuffixLength::Two, diff --git a/src/settings/configuration.rs b/src/settings/configuration.rs index 77c48bf9c9c19f..e6464b3a797968 100644 --- a/src/settings/configuration.rs +++ b/src/settings/configuration.rs @@ -20,7 +20,7 @@ use crate::settings::types::{ FilePattern, PerFileIgnore, PythonVersion, SerializationFormat, Version, }; use crate::{ - flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_import_conventions, + flake8_annotations, flake8_bandit, flake8_bugbear, flake8_errmsg, flake8_import_conventions, flake8_pytest_style, flake8_quotes, flake8_tidy_imports, flake8_unused_arguments, fs, isort, mccabe, pep8_naming, pycodestyle, pydocstyle, pyupgrade, }; @@ -56,6 +56,7 @@ pub struct Configuration { pub update_check: Option, // Plugins pub flake8_annotations: Option, + pub flake8_bandit: Option, pub flake8_bugbear: Option, pub flake8_errmsg: Option, pub flake8_import_conventions: Option, @@ -155,6 +156,7 @@ impl Configuration { update_check: options.update_check, // Plugins flake8_annotations: options.flake8_annotations, + flake8_bandit: options.flake8_bandit, flake8_bugbear: options.flake8_bugbear, flake8_errmsg: options.flake8_errmsg, flake8_import_conventions: options.flake8_import_conventions, @@ -217,6 +219,7 @@ impl Configuration { update_check: self.update_check.or(config.update_check), // Plugins flake8_annotations: self.flake8_annotations.or(config.flake8_annotations), + flake8_bandit: self.flake8_bandit.or(config.flake8_bandit), flake8_bugbear: self.flake8_bugbear.or(config.flake8_bugbear), flake8_errmsg: self.flake8_errmsg.or(config.flake8_errmsg), flake8_import_conventions: self diff --git a/src/settings/mod.rs b/src/settings/mod.rs index a5b38829561e5b..f44e0f4c664059 100644 --- a/src/settings/mod.rs +++ b/src/settings/mod.rs @@ -24,7 +24,7 @@ use crate::settings::types::{ FilePattern, PerFileIgnore, PythonVersion, SerializationFormat, Version, }; use crate::{ - flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_import_conventions, + flake8_annotations, flake8_bandit, flake8_bugbear, flake8_errmsg, flake8_import_conventions, flake8_pytest_style, flake8_quotes, flake8_tidy_imports, flake8_unused_arguments, isort, mccabe, one_time_warning, pep8_naming, pycodestyle, pydocstyle, pyupgrade, }; @@ -64,6 +64,7 @@ pub struct Settings { pub update_check: bool, // Plugins pub flake8_annotations: flake8_annotations::settings::Settings, + pub flake8_bandit: flake8_bandit::settings::Settings, pub flake8_bugbear: flake8_bugbear::settings::Settings, pub flake8_errmsg: flake8_errmsg::settings::Settings, pub flake8_import_conventions: flake8_import_conventions::settings::Settings, @@ -184,6 +185,10 @@ impl Settings { .flake8_annotations .map(std::convert::Into::into) .unwrap_or_default(), + flake8_bandit: config + .flake8_bandit + .map(std::convert::Into::into) + .unwrap_or_default(), flake8_bugbear: config .flake8_bugbear .map(std::convert::Into::into) @@ -264,6 +269,7 @@ impl Settings { task_tags: vec!["TODO".to_string(), "FIXME".to_string()], update_check: false, flake8_annotations: flake8_annotations::settings::Settings::default(), + flake8_bandit: flake8_bandit::settings::Settings::default(), flake8_bugbear: flake8_bugbear::settings::Settings::default(), flake8_errmsg: flake8_errmsg::settings::Settings::default(), flake8_import_conventions: flake8_import_conventions::settings::Settings::default(), @@ -305,6 +311,7 @@ impl Settings { task_tags: vec!["TODO".to_string()], update_check: false, flake8_annotations: flake8_annotations::settings::Settings::default(), + flake8_bandit: flake8_bandit::settings::Settings::default(), flake8_bugbear: flake8_bugbear::settings::Settings::default(), flake8_errmsg: flake8_errmsg::settings::Settings::default(), flake8_import_conventions: flake8_import_conventions::settings::Settings::default(), @@ -365,6 +372,7 @@ impl Hash for Settings { self.target_version.hash(state); // Add plugin properties in alphabetical order. self.flake8_annotations.hash(state); + self.flake8_bandit.hash(state); self.flake8_bugbear.hash(state); self.flake8_errmsg.hash(state); self.flake8_import_conventions.hash(state); diff --git a/src/settings/options.rs b/src/settings/options.rs index 094cfe9dcc79aa..2a64ce1564a142 100644 --- a/src/settings/options.rs +++ b/src/settings/options.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use crate::registry_gen::CheckCodePrefix; use crate::settings::types::{PythonVersion, SerializationFormat, Version}; use crate::{ - flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_import_conventions, + flake8_annotations, flake8_bandit, flake8_bugbear, flake8_errmsg, flake8_import_conventions, flake8_pytest_style, flake8_quotes, flake8_tidy_imports, flake8_unused_arguments, isort, mccabe, pep8_naming, pycodestyle, pydocstyle, pyupgrade, }; @@ -362,6 +362,9 @@ pub struct Options { /// Options for the `flake8-annotations` plugin. pub flake8_annotations: Option, #[option_group] + /// Options for the `flake8-bandit` plugin. + pub flake8_bandit: Option, + #[option_group] /// Options for the `flake8-bugbear` plugin. pub flake8_bugbear: Option, #[option_group] diff --git a/src/settings/pyproject.rs b/src/settings/pyproject.rs index cb21804745b9a0..d6c0b70a4693c8 100644 --- a/src/settings/pyproject.rs +++ b/src/settings/pyproject.rs @@ -191,6 +191,7 @@ mod tests { task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -247,6 +248,7 @@ line-length = 79 update_check: None, cache_dir: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -303,8 +305,9 @@ exclude = ["foo.py"] task_tags: None, update_check: None, flake8_annotations: None, - flake8_errmsg: None, + flake8_bandit: None, flake8_bugbear: None, + flake8_errmsg: None, flake8_pytest_style: None, flake8_quotes: None, flake8_tidy_imports: None, @@ -359,6 +362,7 @@ select = ["E501"] task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -416,6 +420,7 @@ ignore = ["E501"] task_tags: None, update_check: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: None, flake8_errmsg: None, flake8_pytest_style: None, @@ -514,6 +519,7 @@ other-attribute = 1 target_version: None, show_source: None, flake8_annotations: None, + flake8_bandit: None, flake8_bugbear: Some(flake8_bugbear::settings::Options { extend_immutable_calls: Some(vec![ "fastapi.Depends".to_string(),