From 07cbdb7eba3c6097db81cbeaf565916afd9e4ad5 Mon Sep 17 00:00:00 2001 From: Friday Date: Tue, 17 Feb 2026 09:18:09 +0000 Subject: [PATCH 1/2] Fix spurious nosec warning on f-strings with specific test IDs When a `# nosec B608` comment successfully suppressed an issue in an f-string, bandit emitted a spurious warning "nosec encountered (B608), but no failed test on line N" for the other Constant sub-nodes of the JoinedStr that intentionally returned no result. Track which (test_id, line) pairs have been suppressed and skip the warning when the same test was already suppressed on the same line range. Fixes #1204 Co-Authored-By: Claude Opus 4.6 --- bandit/core/tester.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/bandit/core/tester.py b/bandit/core/tester.py index e92c29fb0..127f1f743 100644 --- a/bandit/core/tester.py +++ b/bandit/core/tester.py @@ -22,6 +22,7 @@ def __init__(self, testset, debug, nosec_lines, metrics): self.debug = debug self.nosec_lines = nosec_lines self.metrics = metrics + self.skipped_pairs = set() def run_tests(self, raw_context, checktype): """Runs all tests for a certain type of check, for example @@ -69,9 +70,7 @@ def run_tests(self, raw_context, checktype): result.linerange = temp_context["linerange"] if result.col_offset == -1: result.col_offset = temp_context["col_offset"] - result.end_col_offset = temp_context.get( - "end_col_offset", 0 - ) + result.end_col_offset = temp_context.get("end_col_offset", 0) result.test = name if result.test_id == "": result.test_id = test._test_id @@ -87,10 +86,11 @@ def run_tests(self, raw_context, checktype): self.metrics.note_nosec() continue if result.test_id in nosec_tests_to_skip: - LOG.debug( - f"skipped, nosec for test {result.test_id}" - ) + LOG.debug(f"skipped, nosec for test {result.test_id}") self.metrics.note_skipped_test() + if result.linerange: + for ln in result.linerange: + self.skipped_pairs.add((result.test_id, ln)) continue self.results.append(result) @@ -103,12 +103,12 @@ def run_tests(self, raw_context, checktype): val = constants.RANKING_VALUES[result.confidence] scores["CONFIDENCE"][con] += val else: - nosec_tests_to_skip = self._get_nosecs_from_contexts( - temp_context - ) + nosec_tests_to_skip = self._get_nosecs_from_contexts(temp_context) if ( nosec_tests_to_skip and test._test_id in nosec_tests_to_skip + and (test._test_id, temp_context["lineno"]) + not in self.skipped_pairs ): LOG.warning( f"nosec encountered ({test._test_id}), but no " @@ -130,9 +130,7 @@ def _get_nosecs_from_contexts(self, context, test_result=None): """ nosec_tests_to_skip = set() base_tests = ( - self.nosec_lines.get(test_result.lineno, None) - if test_result - else None + self.nosec_lines.get(test_result.lineno, None) if test_result else None ) context_tests = utils.get_nosec(self.nosec_lines, context) From f44b4f972b0dcb84288efb001b405fc3495e3976 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 09:18:35 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bandit/core/tester.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bandit/core/tester.py b/bandit/core/tester.py index 127f1f743..e6af038ed 100644 --- a/bandit/core/tester.py +++ b/bandit/core/tester.py @@ -70,7 +70,9 @@ def run_tests(self, raw_context, checktype): result.linerange = temp_context["linerange"] if result.col_offset == -1: result.col_offset = temp_context["col_offset"] - result.end_col_offset = temp_context.get("end_col_offset", 0) + result.end_col_offset = temp_context.get( + "end_col_offset", 0 + ) result.test = name if result.test_id == "": result.test_id = test._test_id @@ -86,11 +88,15 @@ def run_tests(self, raw_context, checktype): self.metrics.note_nosec() continue if result.test_id in nosec_tests_to_skip: - LOG.debug(f"skipped, nosec for test {result.test_id}") + LOG.debug( + f"skipped, nosec for test {result.test_id}" + ) self.metrics.note_skipped_test() if result.linerange: for ln in result.linerange: - self.skipped_pairs.add((result.test_id, ln)) + self.skipped_pairs.add( + (result.test_id, ln) + ) continue self.results.append(result) @@ -103,7 +109,9 @@ def run_tests(self, raw_context, checktype): val = constants.RANKING_VALUES[result.confidence] scores["CONFIDENCE"][con] += val else: - nosec_tests_to_skip = self._get_nosecs_from_contexts(temp_context) + nosec_tests_to_skip = self._get_nosecs_from_contexts( + temp_context + ) if ( nosec_tests_to_skip and test._test_id in nosec_tests_to_skip @@ -130,7 +138,9 @@ def _get_nosecs_from_contexts(self, context, test_result=None): """ nosec_tests_to_skip = set() base_tests = ( - self.nosec_lines.get(test_result.lineno, None) if test_result else None + self.nosec_lines.get(test_result.lineno, None) + if test_result + else None ) context_tests = utils.get_nosec(self.nosec_lines, context)