From 8001a1639c68caf0c6d9b5100cee625cee9d27da Mon Sep 17 00:00:00 2001 From: Maksudul Haque Date: Mon, 23 Jan 2023 23:37:33 +0600 Subject: [PATCH] [`flake8-bandit`] Added Rule `S612` (Use of insecure `logging.config.listen`) (#2108) ref: https://github.com/charliermarsh/ruff/issues/1646 --- README.md | 1 + resources/test/fixtures/flake8_bandit/S612.py | 8 ++++ ruff.schema.json | 3 ++ src/checkers/ast.rs | 9 +++++ src/registry.rs | 1 + src/rules/flake8_bandit/mod.rs | 1 + .../rules/logging_config_insecure_listen.rs | 40 +++++++++++++++++++ src/rules/flake8_bandit/rules/mod.rs | 4 ++ ...s__flake8_bandit__tests__S612_S612.py.snap | 15 +++++++ 9 files changed, 82 insertions(+) create mode 100644 resources/test/fixtures/flake8_bandit/S612.py create mode 100644 src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs create mode 100644 src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S612_S612.py.snap diff --git a/README.md b/README.md index 1b93d32429f78..d163a6738e1cf 100644 --- a/README.md +++ b/README.md @@ -812,6 +812,7 @@ For more, see [flake8-bandit](https://pypi.org/project/flake8-bandit/) on PyPI. | S506 | unsafe-yaml-load | Probable use of unsafe loader `{name}` with `yaml.load`. Allows instantiation of arbitrary objects. Consider `yaml.safe_load`. | | | S508 | snmp-insecure-version | The use of SNMPv1 and SNMPv2 is insecure. Use SNMPv3 if able. | | | S509 | snmp-weak-cryptography | You should not use SNMPv3 without encryption. `noAuthNoPriv` & `authNoPriv` is insecure. | | +| S612 | logging-config-insecure-listen | Use of insecure `logging.config.listen` detected | | | S701 | jinja2-autoescape-false | Using jinja2 templates with `autoescape=False` is dangerous and can lead to XSS. Ensure `autoescape=True` or use the `select_autoescape` function. | | ### flake8-blind-except (BLE) diff --git a/resources/test/fixtures/flake8_bandit/S612.py b/resources/test/fixtures/flake8_bandit/S612.py new file mode 100644 index 0000000000000..af6f85f89ff03 --- /dev/null +++ b/resources/test/fixtures/flake8_bandit/S612.py @@ -0,0 +1,8 @@ +import logging.config + +t = logging.config.listen(9999) + +def verify_func(): + pass + +l = logging.config.listen(9999, verify=verify_func) diff --git a/ruff.schema.json b/ruff.schema.json index 2a310b20c6adf..20840f00dbb52 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -1727,6 +1727,9 @@ "S506", "S508", "S509", + "S6", + "S61", + "S612", "S7", "S70", "S701", diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index b342d30e2564d..4ebbd2fc5073e 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -2258,6 +2258,15 @@ where if self.settings.rules.enabled(&Rule::RequestWithoutTimeout) { flake8_bandit::rules::request_without_timeout(self, func, args, keywords); } + if self + .settings + .rules + .enabled(&Rule::LoggingConfigInsecureListen) + { + flake8_bandit::rules::logging_config_insecure_listen( + self, func, args, keywords, + ); + } // flake8-comprehensions if self.settings.rules.enabled(&Rule::UnnecessaryGeneratorList) { diff --git a/src/registry.rs b/src/registry.rs index 68f40ffaddced..648258ca762c7 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -338,6 +338,7 @@ ruff_macros::define_rule_mapping!( S506 => violations::UnsafeYAMLLoad, S508 => violations::SnmpInsecureVersion, S509 => violations::SnmpWeakCryptography, + S612 => rules::flake8_bandit::rules::LoggingConfigInsecureListen, S701 => violations::Jinja2AutoescapeFalse, // flake8-boolean-trap FBT001 => violations::BooleanPositionalArgInFunctionDefinition, diff --git a/src/rules/flake8_bandit/mod.rs b/src/rules/flake8_bandit/mod.rs index a6a4bb25a7399..e6eab6b2f32df 100644 --- a/src/rules/flake8_bandit/mod.rs +++ b/src/rules/flake8_bandit/mod.rs @@ -28,6 +28,7 @@ mod tests { #[test_case(Rule::UnsafeYAMLLoad, Path::new("S506.py"); "S506")] #[test_case(Rule::SnmpInsecureVersion, Path::new("S508.py"); "S508")] #[test_case(Rule::SnmpWeakCryptography, Path::new("S509.py"); "S509")] + #[test_case(Rule::LoggingConfigInsecureListen, Path::new("S612.py"); "S612")] #[test_case(Rule::Jinja2AutoescapeFalse, Path::new("S701.py"); "S701")] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.code(), path.to_string_lossy()); diff --git a/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs b/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs new file mode 100644 index 0000000000000..e08e508068ea5 --- /dev/null +++ b/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs @@ -0,0 +1,40 @@ +use ruff_macros::derive_message_formats; +use rustpython_ast::{Expr, Keyword}; + +use crate::ast::helpers::SimpleCallArgs; +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 LoggingConfigInsecureListen; +); +impl Violation for LoggingConfigInsecureListen { + #[derive_message_formats] + fn message(&self) -> String { + format!("Use of insecure `logging.config.listen` detected") + } +} + +/// S612 +pub fn logging_config_insecure_listen( + checker: &mut Checker, + func: &Expr, + args: &[Expr], + keywords: &[Keyword], +) { + if checker.resolve_call_path(func).map_or(false, |call_path| { + call_path.as_slice() == ["logging", "config", "listen"] + }) { + let call_args = SimpleCallArgs::new(args, keywords); + + if call_args.get_argument("verify", None).is_none() { + checker.diagnostics.push(Diagnostic::new( + LoggingConfigInsecureListen, + Range::from_located(func), + )); + } + } +} diff --git a/src/rules/flake8_bandit/rules/mod.rs b/src/rules/flake8_bandit/rules/mod.rs index f6845b2ee3abe..ea6d6544693e1 100644 --- a/src/rules/flake8_bandit/rules/mod.rs +++ b/src/rules/flake8_bandit/rules/mod.rs @@ -10,6 +10,9 @@ pub use hardcoded_password_string::{ pub use hardcoded_tmp_directory::hardcoded_tmp_directory; pub use hashlib_insecure_hash_functions::hashlib_insecure_hash_functions; pub use jinja2_autoescape_false::jinja2_autoescape_false; +pub use logging_config_insecure_listen::{ + logging_config_insecure_listen, LoggingConfigInsecureListen, +}; pub use request_with_no_cert_validation::request_with_no_cert_validation; pub use request_without_timeout::request_without_timeout; pub use snmp_insecure_version::snmp_insecure_version; @@ -26,6 +29,7 @@ mod hardcoded_password_string; mod hardcoded_tmp_directory; mod hashlib_insecure_hash_functions; mod jinja2_autoescape_false; +mod logging_config_insecure_listen; mod request_with_no_cert_validation; mod request_without_timeout; mod snmp_insecure_version; diff --git a/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S612_S612.py.snap b/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S612_S612.py.snap new file mode 100644 index 0000000000000..f5281465de44f --- /dev/null +++ b/src/rules/flake8_bandit/snapshots/ruff__rules__flake8_bandit__tests__S612_S612.py.snap @@ -0,0 +1,15 @@ +--- +source: src/rules/flake8_bandit/mod.rs +expression: diagnostics +--- +- kind: + LoggingConfigInsecureListen: ~ + location: + row: 3 + column: 4 + end_location: + row: 3 + column: 25 + fix: ~ + parent: ~ +