Skip to content

Commit

Permalink
PyCQA#640 - exit zero severity
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejstromich committed Jun 12, 2021
1 parent 193c355 commit b249baf
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 2 deletions.
25 changes: 23 additions & 2 deletions bandit/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ def main():
parser.add_argument('--exit-zero', action='store_true', dest='exit_zero',
default=False, help='exit with 0, '
'even with results found')
parser.add_argument(
'--exit-zero-severity', dest='exit_zero_severity_string', action='store', default=None,
help='control which severity makes bandit to exit with zero status code. '
'Lower severities to the specified one are included implicitly'
)
python_ver = sys.version.replace('\n', '')
parser.add_argument(
'--version', action='version',
Expand Down Expand Up @@ -343,6 +348,17 @@ def main():
args.confidence = 4
# Other strings will be blocked by argparse

if args.exit_zero_severity_string is not None:
if args.exit_zero_severity_string == "all":
args.exit_zero_severity = 1
elif args.exit_zero_severity_string == "low":
args.exit_zero_severity = 2
elif args.exit_zero_severity_string == "medium":
args.exit_zero_severity = 3
elif args.exit_zero_severity_string == "high":
args.exit_zero_severity = 4
# Other strings will be blocked by argparse

try:
b_conf = b_config.BanditConfig(config_file=args.config_file)
except utils.ConfigError as e:
Expand Down Expand Up @@ -520,8 +536,13 @@ def main():
args.output_format,
args.msg_template)

if (b_mgr.results_count(sev_filter=sev_level, conf_filter=conf_level) > 0
and not args.exit_zero):
if args.exit_zero:
sys.exit(0)

if "exit_zero_severity" in args and not b_mgr.above_threshold_results(args.exit_zero_severity):
sys.exit(0)

if b_mgr.results_count(sev_filter=sev_level, conf_filter=conf_level) > 0:
sys.exit(1)
else:
sys.exit(0)
Expand Down
18 changes: 18 additions & 0 deletions bandit/core/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,24 @@ def _execute_ast_visitor(self, fname, data, nosec_lines):
self.results.extend(res.tester.results)
return score

def above_threshold_results(self, exit_zero_severity):
"""
this method takes args.exit_zero_severity and checkes the count of results of all severities above the defined exit zero severity.
if any of the above severities reports > 0 results this method returns True else it returns False
"""
items_in_rankings = len(b_constants.RANKING)
# this is the minimal level we shouldn't exit with 0
non_exit_zero_severity = exit_zero_severity + 1

while non_exit_zero_severity <= items_in_rankings:
some_var = b_constants.RANKING[non_exit_zero_severity - 1]
results_count = self.results_count(sev_filter=some_var)
non_exit_zero_severity += 1

if results_count > 0:
return True

return False

def _get_files_from_dir(files_dir, included_globs=None,
excluded_path_strings=None):
Expand Down
2 changes: 2 additions & 0 deletions doc/source/man/bandit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ OPTIONS
--ini INI_PATH path to a .bandit file that supplies command line
arguments
--exit-zero exit with 0, even with results found
--exit-zero-severity control which severity makes bandit to exit with zero status code.
Lower severities to the specified one are included implicitly
--version show program's version number and exit

CUSTOM FORMATTING
Expand Down
32 changes: 32 additions & 0 deletions tests/unit/cli/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,35 @@ def test_main_exit_with_results_and_with_exit_zero_flag(self):
mock_mgr_results_ct.return_value = 1

self.assertRaisesRegex(SystemExit, '0', bandit.main)

@mock.patch('sys.argv', ['bandit', '-c', 'bandit.yaml', 'test', '-o',
'output', '--exit-zero-severity', 'low'])
def test_main_exit_with_results_and_with_exit_zero_severity_flag_set_to_some_value_returning_true(self):
# Test that bandit exits with 0 on results and zero flag
temp_directory = self.useFixture(fixtures.TempDir()).path
os.chdir(temp_directory)
with open('bandit.yaml', 'wt') as fd:
fd.write(bandit_config_content)
with mock.patch('bandit.core.manager.BanditManager.results_count'
) as mock_mgr_results_ct:
mock_mgr_results_ct.return_value = 2
with mock.patch('bandit.core.manager.BanditManager.above_threshold_results'
) as mock_mgr_above_threshold_results_ct:
mock_mgr_above_threshold_results_ct.return_value = True


self.assertRaisesRegex(SystemExit, '1', bandit.main)

@mock.patch('sys.argv', ['bandit', '-c', 'bandit.yaml', 'test', '-o',
'output', '--exit-zero-severity', 'medium'])
def test_main_exit_with_results_and_with_exit_zero_severity_flag_set_to_some_value_returning_false(self):
# Test that bandit exits with 0 on results and zero flag
temp_directory = self.useFixture(fixtures.TempDir()).path
os.chdir(temp_directory)
with open('bandit.yaml', 'wt') as fd:
fd.write(bandit_config_content)
with mock.patch('bandit.core.manager.BanditManager.above_threshold_results'
) as mock_mgr_above_threshold_results_ct:
mock_mgr_above_threshold_results_ct.return_value = False

self.assertRaisesRegex(SystemExit, '0', bandit.main)
35 changes: 35 additions & 0 deletions tests/unit/core/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,38 @@ def test_find_candidate_matches(self):
{issue_a: [issue_a, issue_b], issue_b: [issue_a, issue_b]},
manager._find_candidate_matches([issue_a, issue_b],
[issue_a, issue_b, issue_c]))

def test_above_threshold_medium_severity_results_true(self):
levels = [constants.LOW, constants.MEDIUM]
self.manager.results = (
[issue.Issue(severity=level, confidence=level)
for level in levels])
self.assertTrue(self.manager.above_threshold_results(2))

def test_above_threshold_high_severity_results_true(self):
levels = [constants.LOW, constants.HIGH]
self.manager.results = (
[issue.Issue(severity=level, confidence=level)
for level in levels])
self.assertTrue(self.manager.above_threshold_results(2))

def test_above_threshold_low_severity_results_false(self):
levels = [constants.LOW]
self.manager.results = (
[issue.Issue(severity=level, confidence=level)
for level in levels])
self.assertFalse(self.manager.above_threshold_results(2))

def test_above_threshold_medium_severity_results_false(self):
levels = [constants.MEDIUM]
self.manager.results = (
[issue.Issue(severity=level, confidence=level)
for level in levels])
self.assertFalse(self.manager.above_threshold_results(3))

def test_above_threshold_high_severity_results_false(self):
levels = [constants.HIGH]
self.manager.results = (
[issue.Issue(severity=level, confidence=level)
for level in levels])
self.assertFalse(self.manager.above_threshold_results(4))

0 comments on commit b249baf

Please sign in to comment.