diff --git a/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py b/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py index d60b808cb584a1..1689af66e63c5b 100644 --- a/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py +++ b/crates/ruff/resources/test/fixtures/flake8_bandit/S108.py @@ -14,3 +14,19 @@ # not ok by config with open("/foo/bar", "w") as f: f.write("def") + +# Using `tempfile` module should be ok +import tempfile +from tempfile import TemporaryDirectory + +with tempfile.NamedTemporaryFile(dir="/tmp") as f: + f.write(b"def") + +with tempfile.NamedTemporaryFile(dir="/var/tmp") as f: + f.write(b"def") + +with tempfile.TemporaryDirectory(dir="/dev/shm") as d: + pass + +with TemporaryDirectory(dir="/tmp") as d: + pass diff --git a/crates/ruff/src/checkers/ast/analyze/expression.rs b/crates/ruff/src/checkers/ast/analyze/expression.rs index 66e96789556bb4..8589509796804b 100644 --- a/crates/ruff/src/checkers/ast/analyze/expression.rs +++ b/crates/ruff/src/checkers/ast/analyze/expression.rs @@ -1229,13 +1229,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { } } if checker.enabled(Rule::HardcodedTempFile) { - if let Some(diagnostic) = flake8_bandit::rules::hardcoded_tmp_directory( - expr, - value, - &checker.settings.flake8_bandit.hardcoded_tmp_directory, - ) { - checker.diagnostics.push(diagnostic); - } + flake8_bandit::rules::hardcoded_tmp_directory(checker, expr, value); } if checker.enabled(Rule::UnicodeKindPrefix) { pyupgrade::rules::unicode_kind_prefix(checker, expr, kind.as_deref()); diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs index 7993dd1b24a1a1..c677e9e909f2c5 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_tmp_directory.rs @@ -1,8 +1,10 @@ -use ruff_python_ast::{Expr, Ranged}; +use ruff_python_ast::{self as ast, Expr, Ranged}; use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use crate::checkers::ast::Checker; + /// ## What it does /// Checks for the use of hardcoded temporary file or directory paths. /// @@ -49,19 +51,33 @@ impl Violation for HardcodedTempFile { } /// S108 -pub(crate) fn hardcoded_tmp_directory( - expr: &Expr, - value: &str, - prefixes: &[String], -) -> Option { - if prefixes.iter().any(|prefix| value.starts_with(prefix)) { - Some(Diagnostic::new( - HardcodedTempFile { - string: value.to_string(), - }, - expr.range(), - )) - } else { - None +pub(crate) fn hardcoded_tmp_directory(checker: &mut Checker, expr: &Expr, value: &str) { + if !checker + .settings + .flake8_bandit + .hardcoded_tmp_directory + .iter() + .any(|prefix| value.starts_with(prefix)) + { + return; + } + + if let Some(Expr::Call(ast::ExprCall { func, .. })) = + checker.semantic().current_expression_parent() + { + if checker + .semantic() + .resolve_call_path(func) + .is_some_and(|call_path| matches!(call_path.as_slice(), ["tempfile", ..])) + { + return; + } } + + checker.diagnostics.push(Diagnostic::new( + HardcodedTempFile { + string: value.to_string(), + }, + expr.range(), + )); }