[`flake8-bandit`] Add Rule S110 (try/except/pass) (#2197)

This commit is contained in:
Samuel Cormier-Iijima 2023-01-27 18:52:55 -05:00 committed by GitHub
parent b692921160
commit dd15c69181
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 186 additions and 0 deletions

View File

@ -826,6 +826,7 @@ For more, see [flake8-bandit](https://pypi.org/project/flake8-bandit/) on PyPI.
| S106 | hardcoded-password-func-arg | Possible hardcoded password: "{}" | | | S106 | hardcoded-password-func-arg | Possible hardcoded password: "{}" | |
| S107 | hardcoded-password-default | Possible hardcoded password: "{}" | | | S107 | hardcoded-password-default | Possible hardcoded password: "{}" | |
| S108 | hardcoded-temp-file | Probable insecure usage of temporary file or directory: "{}" | | | S108 | hardcoded-temp-file | Probable insecure usage of temporary file or directory: "{}" | |
| S110 | try-except-pass | `try`-`except`-`pass` detected, consider logging the exception | |
| S113 | request-without-timeout | Probable use of requests call with timeout set to `{value}` | | | S113 | request-without-timeout | Probable use of requests call with timeout set to `{value}` | |
| S324 | hashlib-insecure-hash-function | Probable use of insecure hash functions in `hashlib`: "{}" | | | S324 | hashlib-insecure-hash-function | Probable use of insecure hash functions in `hashlib`: "{}" | |
| S501 | request-with-no-cert-validation | Probable use of `{string}` call with `verify=False` disabling SSL certificate checks | | | S501 | request-with-no-cert-validation | Probable use of `{string}` call with `verify=False` disabling SSL certificate checks | |
@ -2682,6 +2683,24 @@ suppress-none-returning = true
### `flake8-bandit` ### `flake8-bandit`
#### [`check-typed-exception`](#check-typed-exception)
Whether to disallow `try`-`except`-`pass` (`S110`) for specific exception types. By default,
`try`-`except`-`pass` is only disallowed for `Exception` and `BaseException`.
**Default value**: `false`
**Type**: `bool`
**Example usage**:
```toml
[tool.ruff.flake8-bandit]
check-typed-exception = true
```
---
#### [`hardcoded-tmp-directory`](#hardcoded-tmp-directory) #### [`hardcoded-tmp-directory`](#hardcoded-tmp-directory)
A list of directories to consider temporary. A list of directories to consider temporary.

View File

@ -0,0 +1,14 @@
try:
pass
except Exception:
pass
try:
pass
except:
pass
try:
pass
except ValueError:
pass

View File

@ -578,6 +578,13 @@
"Flake8BanditOptions": { "Flake8BanditOptions": {
"type": "object", "type": "object",
"properties": { "properties": {
"check-typed-exception": {
"description": "Whether to disallow `try`-`except`-`pass` (`S110`) for specific exception types. By default, `try`-`except`-`pass` is only disallowed for `Exception` and `BaseException`.",
"type": [
"boolean",
"null"
]
},
"hardcoded-tmp-directory": { "hardcoded-tmp-directory": {
"description": "A list of directories to consider temporary.", "description": "A list of directories to consider temporary.",
"type": [ "type": [
@ -1753,6 +1760,7 @@
"S107", "S107",
"S108", "S108",
"S11", "S11",
"S110",
"S113", "S113",
"S3", "S3",
"S32", "S32",

View File

@ -3447,6 +3447,15 @@ where
body, body,
); );
} }
if self.settings.rules.enabled(&Rule::TryExceptPass) {
flake8_bandit::rules::try_except_pass(
self,
type_.as_deref(),
name.as_deref(),
body,
self.settings.flake8_bandit.check_typed_exception,
);
}
if self.settings.rules.enabled(&Rule::ReraiseNoCause) { if self.settings.rules.enabled(&Rule::ReraiseNoCause) {
tryceratops::rules::reraise_no_cause(self, body); tryceratops::rules::reraise_no_cause(self, body);
} }

View File

@ -333,6 +333,7 @@ ruff_macros::define_rule_mapping!(
S106 => violations::HardcodedPasswordFuncArg, S106 => violations::HardcodedPasswordFuncArg,
S107 => violations::HardcodedPasswordDefault, S107 => violations::HardcodedPasswordDefault,
S108 => violations::HardcodedTempFile, S108 => violations::HardcodedTempFile,
S110 => rules::flake8_bandit::rules::TryExceptPass,
S113 => violations::RequestWithoutTimeout, S113 => violations::RequestWithoutTimeout,
S324 => violations::HashlibInsecureHashFunction, S324 => violations::HashlibInsecureHashFunction,
S501 => violations::RequestWithNoCertValidation, S501 => violations::RequestWithNoCertValidation,

View File

@ -31,6 +31,7 @@ mod tests {
#[test_case(Rule::SnmpWeakCryptography, Path::new("S509.py"); "S509")] #[test_case(Rule::SnmpWeakCryptography, Path::new("S509.py"); "S509")]
#[test_case(Rule::LoggingConfigInsecureListen, Path::new("S612.py"); "S612")] #[test_case(Rule::LoggingConfigInsecureListen, Path::new("S612.py"); "S612")]
#[test_case(Rule::Jinja2AutoescapeFalse, Path::new("S701.py"); "S701")] #[test_case(Rule::Jinja2AutoescapeFalse, Path::new("S701.py"); "S701")]
#[test_case(Rule::TryExceptPass, Path::new("S110.py"); "S110")]
fn rules(rule_code: Rule, path: &Path) -> Result<()> { fn rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", rule_code.code(), path.to_string_lossy()); let snapshot = format!("{}_{}", rule_code.code(), path.to_string_lossy());
let diagnostics = test_path( let diagnostics = test_path(
@ -55,6 +56,7 @@ mod tests {
"/dev/shm".to_string(), "/dev/shm".to_string(),
"/foo".to_string(), "/foo".to_string(),
], ],
check_typed_exception: false,
}, },
..Settings::for_rule(Rule::HardcodedTempFile) ..Settings::for_rule(Rule::HardcodedTempFile)
}, },
@ -62,4 +64,20 @@ mod tests {
assert_yaml_snapshot!("S108_extend", diagnostics); assert_yaml_snapshot!("S108_extend", diagnostics);
Ok(()) Ok(())
} }
#[test]
fn check_typed_exception() -> Result<()> {
let diagnostics = test_path(
Path::new("./resources/test/fixtures/flake8_bandit/S110.py"),
&Settings {
flake8_bandit: super::settings::Settings {
check_typed_exception: true,
..Default::default()
},
..Settings::for_rule(Rule::TryExceptPass)
},
)?;
assert_yaml_snapshot!("S110_typed", diagnostics);
Ok(())
}
} }

View File

@ -17,6 +17,7 @@ pub use request_with_no_cert_validation::request_with_no_cert_validation;
pub use request_without_timeout::request_without_timeout; pub use request_without_timeout::request_without_timeout;
pub use snmp_insecure_version::snmp_insecure_version; pub use snmp_insecure_version::snmp_insecure_version;
pub use snmp_weak_cryptography::snmp_weak_cryptography; pub use snmp_weak_cryptography::snmp_weak_cryptography;
pub use try_except_pass::{try_except_pass, TryExceptPass};
pub use unsafe_yaml_load::unsafe_yaml_load; pub use unsafe_yaml_load::unsafe_yaml_load;
mod assert_used; mod assert_used;
@ -34,4 +35,5 @@ mod request_with_no_cert_validation;
mod request_without_timeout; mod request_without_timeout;
mod snmp_insecure_version; mod snmp_insecure_version;
mod snmp_weak_cryptography; mod snmp_weak_cryptography;
mod try_except_pass;
mod unsafe_yaml_load; mod unsafe_yaml_load;

View File

@ -0,0 +1,43 @@
use ruff_macros::derive_message_formats;
use rustpython_ast::{Expr, Stmt, StmtKind};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::define_violation;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct TryExceptPass;
);
impl Violation for TryExceptPass {
#[derive_message_formats]
fn message(&self) -> String {
format!("`try`-`except`-`pass` detected, consider logging the exception")
}
}
/// S110
pub fn try_except_pass(
checker: &mut Checker,
type_: Option<&Expr>,
_name: Option<&str>,
body: &[Stmt],
check_typed_exception: bool,
) {
if body.len() == 1
&& body[0].node == StmtKind::Pass
&& (check_typed_exception
|| type_.map_or(true, |type_| {
checker.resolve_call_path(type_).map_or(true, |call_path| {
call_path.as_slice() == ["", "Exception"]
|| call_path.as_slice() == ["", "BaseException"]
})
}))
{
checker.diagnostics.push(Diagnostic::new(
TryExceptPass,
Range::from_located(&body[0]),
));
}
}

View File

@ -34,11 +34,20 @@ pub struct Options {
/// A list of directories to consider temporary, in addition to those /// A list of directories to consider temporary, in addition to those
/// specified by `hardcoded-tmp-directory`. /// specified by `hardcoded-tmp-directory`.
pub hardcoded_tmp_directory_extend: Option<Vec<String>>, pub hardcoded_tmp_directory_extend: Option<Vec<String>>,
#[option(
default = "false",
value_type = "bool",
example = "check-typed-exception = true"
)]
/// Whether to disallow `try`-`except`-`pass` (`S110`) for specific exception types. By default,
/// `try`-`except`-`pass` is only disallowed for `Exception` and `BaseException`.
pub check_typed_exception: Option<bool>,
} }
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
pub struct Settings { pub struct Settings {
pub hardcoded_tmp_directory: Vec<String>, pub hardcoded_tmp_directory: Vec<String>,
pub check_typed_exception: bool,
} }
impl From<Options> for Settings { impl From<Options> for Settings {
@ -55,6 +64,7 @@ impl From<Options> for Settings {
.into_iter(), .into_iter(),
) )
.collect(), .collect(),
check_typed_exception: options.check_typed_exception.unwrap_or(false),
} }
} }
} }
@ -64,6 +74,7 @@ impl From<Settings> for Options {
Self { Self {
hardcoded_tmp_directory: Some(settings.hardcoded_tmp_directory), hardcoded_tmp_directory: Some(settings.hardcoded_tmp_directory),
hardcoded_tmp_directory_extend: None, hardcoded_tmp_directory_extend: None,
check_typed_exception: Some(settings.check_typed_exception),
} }
} }
} }
@ -72,6 +83,7 @@ impl Default for Settings {
fn default() -> Self { fn default() -> Self {
Self { Self {
hardcoded_tmp_directory: default_tmp_dirs(), hardcoded_tmp_directory: default_tmp_dirs(),
check_typed_exception: false,
} }
} }
} }

View File

@ -0,0 +1,25 @@
---
source: src/rules/flake8_bandit/mod.rs
expression: diagnostics
---
- kind:
TryExceptPass: ~
location:
row: 4
column: 4
end_location:
row: 4
column: 8
fix: ~
parent: ~
- kind:
TryExceptPass: ~
location:
row: 9
column: 4
end_location:
row: 9
column: 8
fix: ~
parent: ~

View File

@ -0,0 +1,35 @@
---
source: src/rules/flake8_bandit/mod.rs
expression: diagnostics
---
- kind:
TryExceptPass: ~
location:
row: 4
column: 4
end_location:
row: 4
column: 8
fix: ~
parent: ~
- kind:
TryExceptPass: ~
location:
row: 9
column: 4
end_location:
row: 9
column: 8
fix: ~
parent: ~
- kind:
TryExceptPass: ~
location:
row: 14
column: 4
end_location:
row: 14
column: 8
fix: ~
parent: ~