Implement flake8-bandit rule `S108` (#1644)

This commit is contained in:
Edgar R. M 2023-01-04 20:11:13 -06:00 committed by GitHub
parent 30d6688c26
commit 2f71bdfbfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 354 additions and 9 deletions

View File

@ -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)
@ -2362,6 +2363,43 @@ suppress-none-returning = true
---
### `flake8-bandit`
#### [`hardcoded-tmp-directory`](#hardcoded-tmp-directory)
A list of directories to consider temporary.
**Default value**: `["/tmp", "/var/tmp", "/dev/shm"]`
**Type**: `Vec<String>`
**Example usage**:
```toml
[tool.ruff.flake8-bandit]
hardcoded-tmp-directory = ["/foo/bar"]
```
---
#### [`hardcoded-tmp-directory-extend`](#hardcoded-tmp-directory-extend)
A list of directories to consider temporary, in addition to those
specified by `hardcoded-tmp-directory`.
**Default value**: `[]`
**Type**: `Vec<String>`
**Example usage**:
```toml
[tool.ruff.flake8-bandit]
extend-hardcoded-tmp-directory = ["/foo/bar"]
```
---
### `flake8-bugbear`
#### [`extend-immutable-calls`](#extend-immutable-calls)

View File

@ -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,

View File

@ -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")

View File

@ -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,9 +926,11 @@
"S105",
"S106",
"S107",
"S108",
"SIM",
"SIM1",
"SIM10",
"SIM102",
"SIM105",
"SIM11",
"SIM118",
@ -1082,6 +1095,32 @@
},
"additionalProperties": false
},
"Flake8BanditOptions": {
"type": "object",
"properties": {
"hardcoded-tmp-directory": {
"description": "A list of directories to consider temporary.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"hardcoded-tmp-directory-extend": {
"description": "A list of directories to consider temporary, in addition to those specified by `hardcoded-tmp-directory`.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"Flake8BugbearOptions": {
"type": "object",
"properties": {

View File

@ -2536,6 +2536,15 @@ where
self.add_check(check);
}
}
if self.settings.enabled.contains(&CheckCode::S108) {
if let Some(check) = flake8_bandit::checks::hardcoded_tmp_directory(
expr,
value,
&self.settings.flake8_bandit.hardcoded_tmp_directory,
) {
self.add_check(check);
}
}
if self.settings.enabled.contains(&CheckCode::UP025) {
pyupgrade::plugins::rewrite_unicode_literal(self, expr, kind);
}

View File

@ -0,0 +1,16 @@
use rustpython_ast::Expr;
use crate::ast::types::Range;
use crate::registry::{Check, CheckKind};
/// S108
pub fn hardcoded_tmp_directory(expr: &Expr, value: &str, prefixes: &[String]) -> Option<Check> {
if prefixes.iter().any(|prefix| value.starts_with(prefix)) {
Some(Check::new(
CheckKind::HardcodedTempFile(value.to_string()),
Range::from_located(expr),
))
} else {
None
}
}

View File

@ -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_directory::hardcoded_tmp_directory;
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_directory;

View File

@ -1,5 +1,6 @@
pub mod checks;
mod helpers;
pub mod settings;
#[cfg(test)]
mod tests {
@ -10,7 +11,7 @@ mod tests {
use crate::linter::test_path;
use crate::registry::CheckCode;
use crate::settings;
use crate::{flake8_bandit, Settings};
#[test_case(CheckCode::S101, Path::new("S101.py"); "S101")]
#[test_case(CheckCode::S102, Path::new("S102.py"); "S102")]
@ -19,15 +20,36 @@ mod tests {
#[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")]
#[test_case(CheckCode::S108, Path::new("S108.py"); "S108")]
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
let checks = test_path(
Path::new("./resources/test/fixtures/flake8_bandit")
.join(path)
.as_path(),
&settings::Settings::for_rule(check_code),
&Settings::for_rule(check_code),
)?;
insta::assert_yaml_snapshot!(snapshot, checks);
Ok(())
}
#[test]
fn check_hardcoded_tmp_additional_dirs() -> Result<()> {
let checks = test_path(
Path::new("./resources/test/fixtures/flake8_bandit/S108.py"),
&Settings {
flake8_bandit: flake8_bandit::settings::Settings {
hardcoded_tmp_directory: vec![
"/tmp".to_string(),
"/var/tmp".to_string(),
"/dev/shm".to_string(),
"/foo".to_string(),
],
},
..Settings::for_rule(CheckCode::S108)
},
)?;
insta::assert_yaml_snapshot!("S108_extend", checks);
Ok(())
}
}

View File

@ -0,0 +1,77 @@
//! Settings for the `flake8-bandit` plugin.
use ruff_macros::ConfigurationOptions;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
fn default_tmp_dirs() -> Vec<String> {
["/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<String>",
example = "hardcoded-tmp-directory = [\"/foo/bar\"]"
)]
/// A list of directories to consider temporary.
pub hardcoded_tmp_directory: Option<Vec<String>>,
#[option(
default = "[]",
value_type = "Vec<String>",
example = "extend-hardcoded-tmp-directory = [\"/foo/bar\"]"
)]
/// A list of directories to consider temporary, in addition to those
/// specified by `hardcoded-tmp-directory`.
pub hardcoded_tmp_directory_extend: Option<Vec<String>>,
}
#[derive(Debug, Hash)]
pub struct Settings {
pub hardcoded_tmp_directory: Vec<String>,
}
impl From<Options> for Settings {
fn from(options: Options) -> Self {
Self {
hardcoded_tmp_directory: options
.hardcoded_tmp_directory
.unwrap_or_else(default_tmp_dirs)
.into_iter()
.chain(
options
.hardcoded_tmp_directory_extend
.unwrap_or_default()
.into_iter(),
)
.collect(),
}
}
}
impl From<Settings> for Options {
fn from(settings: Settings) -> Self {
Self {
hardcoded_tmp_directory: Some(settings.hardcoded_tmp_directory),
hardcoded_tmp_directory_extend: None,
}
}
}
impl Default for Settings {
fn default() -> Self {
Self {
hardcoded_tmp_directory: default_tmp_dirs(),
}
}
}

View File

@ -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: ~

View File

@ -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: ~

View File

@ -16,9 +16,9 @@ use crate::settings::{flags, Settings};
use crate::source_code_locator::SourceCodeLocator;
use crate::source_code_style::SourceCodeStyleDetector;
use crate::{
directives, flake8_annotations, 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,
directives, 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,
};
const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -116,6 +116,7 @@ pub fn defaultSettings() -> Result<JsValue, JsValue> {
update_check: None,
// Use default options for all plugins.
flake8_annotations: Some(flake8_annotations::settings::Settings::default().into()),
flake8_bandit: Some(flake8_bandit::settings::Settings::default().into()),
flake8_bugbear: Some(flake8_bugbear::settings::Settings::default().into()),
flake8_errmsg: Some(flake8_errmsg::settings::Settings::default().into()),
flake8_pytest_style: Some(flake8_pytest_style::settings::Settings::default().into()),

View File

@ -328,6 +328,7 @@ pub enum CheckCode {
S105,
S106,
S107,
S108,
// flake8-boolean-trap
FBT001,
FBT002,
@ -1062,6 +1063,7 @@ pub enum CheckKind {
HardcodedPasswordString(String),
HardcodedPasswordFuncArg(String),
HardcodedPasswordDefault(String),
HardcodedTempFile(String),
// mccabe
FunctionIsTooComplex(String, usize),
// flake8-boolean-trap
@ -1515,6 +1517,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
@ -1916,6 +1919,7 @@ impl CheckCode {
CheckCode::S105 => CheckCategory::Flake8Bandit,
CheckCode::S106 => CheckCategory::Flake8Bandit,
CheckCode::S107 => CheckCategory::Flake8Bandit,
CheckCode::S108 => CheckCategory::Flake8Bandit,
// flake8-simplify
CheckCode::SIM102 => CheckCategory::Flake8Simplify,
CheckCode::SIM105 => CheckCategory::Flake8Simplify,
@ -2282,6 +2286,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
@ -3218,6 +3223,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

View File

@ -514,6 +514,7 @@ pub enum CheckCodePrefix {
S105,
S106,
S107,
S108,
SIM,
SIM1,
SIM10,
@ -911,6 +912,7 @@ impl CheckCodePrefix {
CheckCode::S105,
CheckCode::S106,
CheckCode::S107,
CheckCode::S108,
CheckCode::FBT001,
CheckCode::FBT002,
CheckCode::FBT003,
@ -2598,6 +2600,7 @@ impl CheckCodePrefix {
CheckCode::S105,
CheckCode::S106,
CheckCode::S107,
CheckCode::S108,
],
CheckCodePrefix::S1 => vec![
CheckCode::S101,
@ -2607,6 +2610,7 @@ impl CheckCodePrefix {
CheckCode::S105,
CheckCode::S106,
CheckCode::S107,
CheckCode::S108,
],
CheckCodePrefix::S10 => vec![
CheckCode::S101,
@ -2616,6 +2620,7 @@ impl CheckCodePrefix {
CheckCode::S105,
CheckCode::S106,
CheckCode::S107,
CheckCode::S108,
],
CheckCodePrefix::S101 => vec![CheckCode::S101],
CheckCodePrefix::S102 => vec![CheckCode::S102],
@ -2624,6 +2629,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::SIM102,
CheckCode::SIM105,
@ -3606,6 +3612,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,

View File

@ -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<bool>,
// Plugins
pub flake8_annotations: Option<flake8_annotations::settings::Options>,
pub flake8_bandit: Option<flake8_bandit::settings::Options>,
pub flake8_bugbear: Option<flake8_bugbear::settings::Options>,
pub flake8_errmsg: Option<flake8_errmsg::settings::Options>,
pub flake8_import_conventions: Option<flake8_import_conventions::settings::Options>,
@ -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

View File

@ -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);

View File

@ -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<flake8_annotations::settings::Options>,
#[option_group]
/// Options for the `flake8-bandit` plugin.
pub flake8_bandit: Option<flake8_bandit::settings::Options>,
#[option_group]
/// Options for the `flake8-bugbear` plugin.
pub flake8_bugbear: Option<flake8_bugbear::settings::Options>,
#[option_group]

View File

@ -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(),