mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
fix(compliance): skip MANUAL findings in section tally to avoid KeyError (#11831)
Co-authored-by: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Co-authored-by: pedrooot <pedromarting3@gmail.com>
This commit is contained in:
@@ -2,6 +2,14 @@
|
||||
|
||||
All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
## [5.32.1] (Prowler UNRELEASED)
|
||||
|
||||
### 🐞 Fixed
|
||||
|
||||
- `KeyError: 'MANUAL'` crash while rendering the compliance summary table (e.g. CIS Microsoft 365) when a framework has manual, checks-less requirements with a Level 1/Level 2 profile; `MANUAL` findings are now skipped in the PASS/FAIL section tally instead of raising [(#11822)](https://github.com/prowler-cloud/prowler/issues/11822)
|
||||
|
||||
---
|
||||
|
||||
## [5.32.0] (Prowler v5.32.0)
|
||||
|
||||
### 🚀 Added
|
||||
|
||||
@@ -395,6 +395,12 @@ def accumulate_group_status(
|
||||
) -> None:
|
||||
"""Count a finding once per group, upgrading a counted PASS to FAIL on conflict (mutates ``counts``/``seen``)."""
|
||||
previous = seen.get(index)
|
||||
if status == "MANUAL":
|
||||
# MANUAL findings come from manual, checks-less requirements and are
|
||||
# informational only: they have no PASS/FAIL/Muted column in the section
|
||||
# tally, so counting them would raise KeyError on counts[status] += 1.
|
||||
# Skip them (an unexpected status still raises loudly below).
|
||||
return
|
||||
if previous is None:
|
||||
seen[index] = status
|
||||
counts[status] += 1
|
||||
|
||||
@@ -351,6 +351,37 @@ class Test_accumulate_group_status:
|
||||
with pytest.raises(KeyError):
|
||||
accumulate_group_status(0, "Muted", counts, {})
|
||||
|
||||
def test_manual_status_is_ignored_not_counted(self):
|
||||
# A MANUAL finding (from a manual, checks-less requirement) has no
|
||||
# PASS/FAIL/Muted column: it must be skipped, not raise KeyError, and
|
||||
# not appear in the tally. Regression test for the M365 CIS compliance
|
||||
# crash "KeyError: 'MANUAL'" (issue #11822).
|
||||
counts = {"FAIL": 0, "PASS": 0}
|
||||
seen = {}
|
||||
accumulate_group_status(0, "MANUAL", counts, seen)
|
||||
assert counts == {"FAIL": 0, "PASS": 0}
|
||||
assert seen == {}
|
||||
|
||||
def test_manual_mixed_with_pass_and_fail(self):
|
||||
# MANUAL findings interleaved with real PASS/FAIL ones only skip
|
||||
# themselves; the PASS/FAIL tally is unaffected.
|
||||
counts = {"FAIL": 0, "PASS": 0}
|
||||
seen = {}
|
||||
accumulate_group_status(0, "MANUAL", counts, seen)
|
||||
accumulate_group_status(1, "PASS", counts, seen)
|
||||
accumulate_group_status(2, "FAIL", counts, seen)
|
||||
accumulate_group_status(3, "MANUAL", counts, seen)
|
||||
assert counts == {"FAIL": 1, "PASS": 1}
|
||||
|
||||
def test_manual_ignored_on_counts_with_muted_key(self):
|
||||
# MANUAL is skipped regardless of the counts shape (e.g. the universal
|
||||
# table's PASS/FAIL/Muted buckets), never creating a "MANUAL" key.
|
||||
counts = {"FAIL": 0, "PASS": 0, "Muted": 0}
|
||||
seen = {}
|
||||
accumulate_group_status(0, "MANUAL", counts, seen)
|
||||
assert counts == {"FAIL": 0, "PASS": 0, "Muted": 0}
|
||||
assert "MANUAL" not in counts
|
||||
|
||||
|
||||
class Test_apply_config_status:
|
||||
def test_none_config_status_keeps_finding(self):
|
||||
|
||||
Reference in New Issue
Block a user