Skip to content

feat(config): add compliance guardrails for the SDK config#11669

Open
pedrooot wants to merge 18 commits into
masterfrom
sdk-config-compliance
Open

feat(config): add compliance guardrails for the SDK config#11669
pedrooot wants to merge 18 commits into
masterfrom
sdk-config-compliance

Conversation

@pedrooot

@pedrooot pedrooot commented Jun 23, 2026

Copy link
Copy Markdown
Member

Description

Some compliance requirements only really pass if the checks behind them ran with a strict enough config. Right now you can loosen a check's config and the requirement still shows up as PASS even though it isn't actually met.

CIS AWS 6.0 req 2.11 is a good example ("credentials unused for 45 days or more are disabled"). It maps to iam_user_accesskey_unused, which reads max_unused_access_keys_days. Bump that to 120 days and the check happily passes, but the requirement clearly isn't satisfied.

So a requirement can now declare what it expects from the config via a new ConfigRequirements field. When we build the compliance outputs we check those expectations against the config the scan actually used (audit_config). If a check ran with a config too loose for the requirement, that requirement is forced to FAIL and we prepend [CONFIG NOT VALID] plus the reason to status_extended.

Each constraint is {Check, ConfigKey, Operator, Value}. Operators:

  • lte / gte / eq for scalars (thresholds, boolean toggles)
  • in –> applied value must be one of Value
  • subset –> applied list must be a subset of Value (allowlists, e.g. recommended_minimal_tls_versions)
  • superset –> applied list must be a superset of Value (denylists, e.g. insecure_key_algorithms)

The actual evaluation lives in one place (prowler/lib/check/compliance_config_eval.py) so the SDK outputs and the App backend share the same logic. The FAIL override is applied to CSV, OCSF and the console tables.

One thing worth calling out: if a ConfigKey isn't explicitly set, we skip the constraint and assume the check's default already matches what the requirement wants. So nothing changes for anyone running the default config.

On the model side: ConfigRequirements on the legacy Compliance_Requirement and config_requirements on UniversalComplianceRequirement, wired through adapt_legacy_to_universal. Then I added the actual ConfigRequirements entries to the relevant requirements across the AWS, Azure, GCP, Alibaba Cloud, Kubernetes, M365 and Okta frameworks, only for requirements whose control text prescribes the concrete value.

Steps to review

Please add a detailed description of how to review this PR.

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me, if not, request it via the issue/feature in here or Prowler Community Slack

SDK/CLI

  • Are there new checks included in this PR? Yes / No
    • If so, do we need to update permissions for the provider? Please review this carefully.

UI

  • All issue/task requirements work as expected on the UI
  • If this PR adds or updates npm dependencies, include package-health evidence (maintenance, popularity, known vulnerabilities, license, release age) and explain why existing/native alternatives are insufficient.
  • Screenshots/Video of the functionality flow (if applicable) - Mobile (X < 640px)
  • Screenshots/Video of the functionality flow (if applicable) - Table (640px > X < 1024px)
  • Screenshots/Video of the functionality flow (if applicable) - Desktop (X > 1024px)
  • Ensure new entries are added to CHANGELOG.md, if applicable.

API

  • All issue/task requirements work as expected on the API
  • Endpoint response output (if applicable)
  • EXPLAIN ANALYZE output for new/modified queries or indexes (if applicable)
  • Performance test results (if applicable)
  • Any other relevant evidence of the implementation (if applicable)
  • Verify if API specs need to be regenerated.
  • Check if version updates are required (e.g., specs, uv, etc.).
  • Ensure new entries are added to CHANGELOG.md, if applicable.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Summary by CodeRabbit

  • New Features
    • Added requirement-level configuration guardrails: configurable checks now report FAIL when the scan’s applied audit configuration violates requirement constraints.
    • Compliance outputs (CSV and console tables) are now config-aware across frameworks and threat scoring, using evaluated “effective” PASS/FAIL and updated status/extended messages.
    • When invalid, statuses are overridden to FAIL and [CONFIG NOT VALID] is appended with the first violated constraint reason.
  • Documentation
    • Expanded guidance for authoring and interpreting configuration guardrails.
  • Tests
    • Added unit and integration tests covering constraint parsing, operator/type semantics, provider scoping, and correct aggregation/muted handling.

@pedrooot pedrooot requested a review from a team as a code owner June 23, 2026 10:28
@github-actions github-actions Bot added the compliance Issues/PRs related with the Compliance Frameworks label Jun 23, 2026
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

✅ All necessary CHANGELOG.md files have been updated.

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds per-requirement configuration validation across all compliance output paths. A new Compliance_Requirement_ConfigConstraint Pydantic model allows compliance JSON files to declare operator-based constraints on scan config keys. A new evaluation module (compliance_config_eval.py) evaluates these constraints against the scan-global audit_config and forces findings to FAIL with a [CONFIG NOT VALID] prefix when constraints are violated. This evaluation is wired into every compliance CSV adapter, console table function, OCSF output, and generic table across all frameworks and cloud providers.

Changes

Per-requirement configuration validation

Layer / File(s) Summary
Compliance constraint schema and model adaptation
prowler/lib/check/compliance_models.py
Adds Compliance_Requirement_ConfigConstraint Pydantic model with restricted Operator literals (lte, gte, eq, in, subset, superset) and polymorphic Value; extends Compliance_Requirement.ConfigRequirements and UniversalComplianceRequirement.config_requirements; updates adapt_legacy_to_universal to serialize constraints as dicts.
Config evaluation engine
prowler/lib/check/compliance_config_eval.py
New module implementing operator evaluation, evaluate_config_constraints, get_scan_audit_config, get_scan_provider_type, build_requirement_config_status, memoized resolve_requirement_config_status, apply_config_status (forces FAIL with [CONFIG NOT VALID] prefix), get_effective_status, and aggregation helpers (accumulate_overview_status, accumulate_group_status).
Schema and model tests
tests/lib/check/compliance_config_constraint_model_test.py
Tests for Compliance_Requirement_ConfigConstraint schema (allowed operators, boolean/list value preservation, required field validation), Compliance model loading from CIS 6.0 AWS JSON, and legacy→universal adaptation with constraint serialization.
Config evaluation engine unit tests
tests/lib/check/compliance_config_eval_test.py
Unit tests for evaluate_config_constraints (all operators, type mismatches, empty constraints), provider scoping, build_requirement_config_status (filtering, legacy/universal shapes), resolve_requirement_config_status (memoization), apply_config_status (FAIL override), get_effective_status, and scan config/provider helpers.
Data-integrity tests for shipped constraints
tests/lib/check/compliance_config_requirements_data_test.py
Parametrized test suite that discovers all compliance JSON files and validates per-constraint schema correctness, operator membership, mapped check inclusion, value type conformance, region-mute invariant enforcement, and provider scoping consistency.
Coverage regression tests and baseline
tests/lib/check/compliance_config_requirements_coverage_test.py, tests/lib/check/compliance_config_requirements_coverage_baseline.json
Coverage test module that statically analyzes check entrypoints to detect which audit_config keys are read, compares against compliance JSON ConfigRequirements to identify gaps, enforces regression invariants against a committed baseline, and verifies schema-enforced keys are genuinely pinned in defaults.
CSV/structured output transform adapters
prowler/lib/outputs/compliance/{asd_essential_eight,aws_well_architected,c5,ccc,cis,cisa_scuba,ens,generic,iso27001,kisa_ismsp,mitre_attack,prowler_threatscore}/*_aws.py, *_azure.py, *_gcp.py, etc.
Homogeneous pattern across 30+ cloud-provider-specific transform() methods: precompute requirement_config_status once via build_requirement_config_status, then call apply_config_status per finding/requirement match to derive row_status/row_status_extended for the output model row's Status and StatusExtended fields.
Console table output rendering
prowler/lib/outputs/compliance/{asd_essential_eight,c5,ccc,cis,ens,kisa_ismsp,mitre_attack,prowler_threatscore}/*.py
Each framework table function fetches audit_config once, memoizes requirement config resolution in config_status_cache, computes effective_status per finding, and uses it to drive PASS/FAIL counts in both overview and per-section tallies; muted counting remains driven by finding.muted.
Universal OCSF, generic, and generic table outputs
prowler/lib/outputs/compliance/{universal,generic}/*.py
_build_compliance_finding accepts config_status and derives compliance_status_id and message from apply_config_status; universal table applies effective_status in grouped, split, and scored rendering modes; generic outputs compute requirement_config_status for GenericComplianceModel rows.
Integration tests for output adapters
tests/lib/outputs/compliance/{cis,ens,universal,iso27001}/*_config_requirements_test.py
Each test injects a patched audit_config via Provider.get_global_provider, runs the output adapter with synthetic findings, and asserts that violating configs force FAIL with CONFIG NOT VALID while compliant or absent configs preserve PASS.
Documentation and changelog
docs/developer-guide/{configurable-checks.mdx,security-compliance-framework.mdx}, prowler/CHANGELOG.md
Updates developer guide with configuration guardrails concepts, constraint schema, evaluation semantics, and operator details; adds changelog entry for per-requirement configuration validation feature.

Sequence Diagram(s)

sequenceDiagram
  participant CSVAdapter as CSV Adapter
  participant BuildReqStatus as build_requirement_config_status
  participant EvalConstraints as evaluate_config_constraints
  participant ApplyStatus as apply_config_status
  participant Output as Output Model

  CSVAdapter->>BuildReqStatus: compliance.Requirements, audit_config
  BuildReqStatus->>EvalConstraints: constraint, audit_config
  EvalConstraints-->>BuildReqStatus: (is_compliant, reason)
  BuildReqStatus-->>CSVAdapter: {req_id: (bool, str)}
  
  loop For each finding/requirement match
    CSVAdapter->>ApplyStatus: finding.status, status_extended, config_status
    ApplyStatus-->>CSVAdapter: (row_status, row_status_extended)
    CSVAdapter->>Output: Status=row_status, StatusExtended=row_status_extended
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • prowler-cloud/prowler#11567: Both PRs modify the same CLI compliance table generator functions (e.g., get_asd_essential_eight_table, get_c5_table, get_ccc_table, etc.)—one to compute config-aware effective_status and related counting, the other to fix per-section undercounting and Provider-column leakage—so the changes overlap directly in the table aggregation/counting/provider logic.

Suggested reviewers

  • danibarranqueroo
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description has a solid summary, but it is missing the required Context section and the Steps to review section is still a placeholder. Add the Context section with motivation and any linked issue, and replace the placeholder Steps to review text with concrete review instructions.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(config): add compliance guardrails for the SDK config' clearly and accurately describes the main feature added—compliance guardrails that enforce configuration constraints on SDK scans.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sdk-config-compliance

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pedrooot pedrooot changed the title chore: merge master feat(config): add compliance guardrails for the SDK config Jun 23, 2026
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🔒 Container Security Scan

Image: prowler:cca7bc1
Last scan: 2026-06-25 10:34:07 UTC

✅ No Vulnerabilities Detected

The container image passed all security checks. No known CVEs were found.

📋 Resources:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
prowler/lib/outputs/compliance/ccc/ccc.py (1)

58-78: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Resolve one final status before updating PASS/FAIL counts.

Because config validation makes effective_status requirement-specific, the same finding can be added to both PASS and FAIL totals when mapped requirements disagree. Section aggregation has the same issue because the first seen status wins. Track the current resolved status and let config-forced FAIL override PASS.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/lib/outputs/compliance/ccc/ccc.py` around lines 58 - 78, The issue is
that effective_status varies per requirement, allowing the same finding to be
counted in both PASS and FAIL totals. Before updating the muted_count,
fail_count, and pass_count lists, you need to resolve a single final status per
finding that aggregates across all its requirements and sections. Implement
logic where a config-forced FAIL status overrides PASS across all requirements
for that finding, then use this resolved final status (instead of the
per-requirement effective_status) to update the overall counts. The same
resolved status should be determined once per finding before the section
iteration loop, ensuring each finding is counted only once in the appropriate
total.
prowler/lib/outputs/compliance/c5/c5.py (1)

58-78: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prevent mixed requirement statuses from double-counting a finding.

effective_status can differ per requirement, but pass_count and fail_count are independent lists. A finding mapped to both a config-invalid requirement and a valid PASS requirement can be counted in both totals, and section counts become order-dependent. Use a single per-finding/per-section resolved status with FAIL taking precedence over PASS.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/lib/outputs/compliance/c5/c5.py` around lines 58 - 78, The issue is
that findings can have different effective_status values across multiple
requirements, and the current code with separate muted_count, fail_count, and
pass_count lists can double-count a single finding if it has conflicting
statuses. Instead of checking if index is not in fail_count or pass_count
independently, track a single resolved status per finding that applies FAIL
precedence (FAIL overrides PASS). Replace the three separate lists with a
dictionary mapping index to a resolved status, then in the overview totals
section check and update only the resolved status for each finding, ensuring
FAIL takes precedence when a finding matches both FAIL and PASS requirements.
Apply the same logic to the per-section counting to maintain consistency.
prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight.py (1)

58-80: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Give FAIL precedence when one finding maps to mixed effective statuses.

effective_status is per requirement now, so the same index can land in both pass_count and fail_count; per-section counts can also keep an earlier PASS and ignore a later config-forced FAIL. Track the resolved status per finding/section and let FAIL override PASS.

Suggested direction
-    pass_count = []
-    fail_count = []
-    muted_count = []
+    pass_count = set()
+    fail_count = set()
+    muted_count = set()
@@
-                            section_seen[section] = set()
+                            section_seen[section] = {}
@@
                         if finding.muted:
-                            if index not in muted_count:
-                                muted_count.append(index)
+                            muted_count.add(index)
+                            fail_count.discard(index)
+                            pass_count.discard(index)
                         elif effective_status == "FAIL":
-                            if index not in fail_count:
-                                fail_count.append(index)
+                            fail_count.add(index)
+                            pass_count.discard(index)
                         elif effective_status == "PASS":
-                            if index not in pass_count:
-                                pass_count.append(index)
+                            if index not in fail_count:
+                                pass_count.add(index)
@@
-                        if index not in section_seen[section]:
-                            section_seen[section].add(index)
-                            if finding.muted:
-                                sections[section]["Muted"] += 1
-                            elif effective_status == "FAIL":
-                                sections[section]["FAIL"] += 1
-                            elif effective_status == "PASS":
-                                sections[section]["PASS"] += 1
+                        previous_status = section_seen[section].get(index)
+                        if finding.muted:
+                            if previous_status is None:
+                                section_seen[section][index] = "Muted"
+                                sections[section]["Muted"] += 1
+                        elif effective_status == "FAIL":
+                            if previous_status == "PASS":
+                                sections[section]["PASS"] -= 1
+                            if previous_status != "FAIL":
+                                section_seen[section][index] = "FAIL"
+                                sections[section]["FAIL"] += 1
+                        elif effective_status == "PASS" and previous_status is None:
+                            section_seen[section][index] = "PASS"
+                            sections[section]["PASS"] += 1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight.py`
around lines 58 - 80, The issue is that the same finding index can have
different effective statuses since effective_status is now per requirement,
causing findings to be counted in multiple status lists or counted with
incorrect status in sections. Instead of using lists (muted_count, fail_count,
pass_count) to track which indices have been counted, change these to
dictionaries that store the resolved status for each index. Similarly, change
section_seen[section] from a set to a dictionary that tracks the resolved status
per finding/section pair. When processing each finding, check if the index
already exists in the status tracking dictionaries: if it does and the new
effective_status is FAIL, let it override any previous PASS status; if the new
status is less severe than what's already recorded (like PASS when FAIL is
already set), skip updating. Apply the same precedence logic (FAIL overrides
PASS) to both the overview-level counts (muted_count, fail_count, pass_count)
and the per-section counts (sections[section]).
prowler/lib/outputs/compliance/universal/universal_table.py (1)

185-217: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Deduplicate after resolving all requirement statuses for the finding.

effective_status now varies by requirement, but grouped/split/scored modes still de-duplicate by finding index in the overview and per-group/per-split scoring structures. A finding mapped to both a config-valid requirement and a config-invalid requirement can be counted as both PASS and FAIL, or the first processed requirement can lock in PASS/score before a later requirement should force FAIL. Collapse all matched requirement statuses first with FAIL precedence per finding and per group/split, or change the de-duplication keys to include req.id if the table is meant to count requirement instances.

Based on the review stack context that config status is resolved per requirement and invalid configs force FAIL.

Also applies to: 303-343, 435-486

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/lib/outputs/compliance/universal/universal_table.py` around lines 185
- 217, The current deduplication logic using finding index only (in muted_count,
fail_count, pass_count lists and group_seen dictionary) does not account for the
fact that effective_status now varies per requirement due to per-requirement
config status resolution. A single finding mapped to multiple requirements can
be counted with conflicting statuses. Either pre-compute a single
effective_status per finding by collapsing all its matched requirement statuses
with FAIL taking precedence before the group_key loop, or change the
deduplication keys to include req.id alongside the finding index to track status
per requirement instance instead of per finding.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@prowler/lib/check/compliance_config_eval.py`:
- Around line 54-76: Update the function signature of
evaluate_config_constraints to use parameterized generic types for better type
safety. Replace the bare list type in config_requirements parameter with
list[dict] and the bare dict type in audit_config parameter with dict[str, Any].
Ensure you import Any from the typing module if not already imported. Apply this
same pattern to other public functions in the module that currently use bare
generic types like list, dict, or tuple without type parameters.
- Around line 110-124: The get_scan_audit_config function catches all exceptions
broadly with a bare except Exception clause, which can hide genuine bugs
unrelated to provider availability. Replace the broad exception handler with
more specific exception types that are expected when the provider is unavailable
or unavoidable (such as AttributeError and ImportError). Alternatively, if
keeping a broad exception handler, add logging to capture unexpected exceptions
before returning the empty dict so that real errors are not silently suppressed
and can aid in debugging.
- Around line 145-220: The public functions build_requirement_config_status,
resolve_requirement_config_status, apply_config_status, and get_effective_status
have inconsistent docstring formatting that does not comply with Google-style
documentation standards. Update each of these function docstrings to include
both Args and Returns sections in a structured format, matching the pattern
already established in evaluate_config_constraints. For
build_requirement_config_status add a Returns section, and for the other three
functions convert the narrative docstrings to include both Args and Returns
sections with proper parameter and return value documentation.

In `@prowler/lib/check/compliance_models.py`:
- Around line 307-334: In the Compliance_Requirement_ConfigConstraint class, the
Value field uses a bare list type without parameterization, reducing type
safety. Replace the bare list in the Union type definition with a parameterized
version such as list[Any] or list[Union[str, int, float]] to explicitly declare
what types are allowed in the list. This will improve type-checker coverage and
clarify the expected constraint value types for operations like subset and
superset.

In `@prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp.py`:
- Around line 72-75: The current implementation allows the same index to be
added to both fail_count and pass_count when a single finding maps to multiple
requirements with different effective_status values. Instead of appending to
separate lists, use a dictionary to track one status per finding (index) with
FAIL taking precedence over PASS. When effective_status is FAIL, set the
finding's status to FAIL; when effective_status is PASS, only set the status if
the finding is not already marked as FAIL. Apply this same FAIL-precedence logic
to the section counts tracking as well (the code around lines 85-87 that also
processes different status values).

In `@prowler/lib/outputs/compliance/mitre_attack/mitre_attack.py`:
- Around line 63-66: When a finding maps to multiple requirements with different
statuses, FAIL should take precedence over PASS. In the section where
effective_status equals FAIL, after adding the index to fail_count, also remove
it from pass_count if it exists there. This ensures that when the same index
appears in both pass_count and fail_count across different requirements, the
FAIL status wins and prevents later config-invalid requirements from incorrectly
upgrading the tactic status. Apply the same logic to the corresponding code
section mentioned in the "Also applies to" reference.

In `@prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore.py`:
- Around line 54-59: The effective_status is calculated per requirement, but the
finding counts (pass_count, fail_count) and deduplication logic (using
pillar_seen, counted_findings_per_pillar, counted_findings_generic) only
deduplicate by finding index. This causes the same finding to be counted
multiple times if it maps to multiple ThreatScore requirements with different
config outcomes. Before updating pass_count and fail_count at the locations
around lines 74-85 and 91-115, aggregate the effective_status across all
requirements for each finding with FAIL taking precedence (so any FAIL status
overrides PASS for that finding), then use the collapsed status to determine
counting. Alternatively, change the deduplication keys from just index to
include requirement.Id if per-requirement counting is intentional.

In `@tests/lib/check/compliance_config_constraint_model_test.py`:
- Line 76: Replace all four instances of the json.load(open(_CIS_6_0)) pattern
at lines 76, 83, 94, and 109 with a context manager using a with statement to
wrap the open() call. This ensures file handles are explicitly closed rather
than relying on garbage collection, following Python best practices for resource
management.

In
`@tests/lib/outputs/compliance/universal/universal_table_config_requirements_test.py`:
- Around line 60-73: The _render function uses a hardcoded
output_directory="/tmp" path which is OS-dependent and not portable across
different systems. Add tmp_path as a parameter to the _render function (which is
a pytest fixture provided automatically) and replace the hardcoded "/tmp" string
with str(tmp_path) in the output_directory argument of the get_universal_table
call to make the test portable.

---

Outside diff comments:
In `@prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight.py`:
- Around line 58-80: The issue is that the same finding index can have different
effective statuses since effective_status is now per requirement, causing
findings to be counted in multiple status lists or counted with incorrect status
in sections. Instead of using lists (muted_count, fail_count, pass_count) to
track which indices have been counted, change these to dictionaries that store
the resolved status for each index. Similarly, change section_seen[section] from
a set to a dictionary that tracks the resolved status per finding/section pair.
When processing each finding, check if the index already exists in the status
tracking dictionaries: if it does and the new effective_status is FAIL, let it
override any previous PASS status; if the new status is less severe than what's
already recorded (like PASS when FAIL is already set), skip updating. Apply the
same precedence logic (FAIL overrides PASS) to both the overview-level counts
(muted_count, fail_count, pass_count) and the per-section counts
(sections[section]).

In `@prowler/lib/outputs/compliance/c5/c5.py`:
- Around line 58-78: The issue is that findings can have different
effective_status values across multiple requirements, and the current code with
separate muted_count, fail_count, and pass_count lists can double-count a single
finding if it has conflicting statuses. Instead of checking if index is not in
fail_count or pass_count independently, track a single resolved status per
finding that applies FAIL precedence (FAIL overrides PASS). Replace the three
separate lists with a dictionary mapping index to a resolved status, then in the
overview totals section check and update only the resolved status for each
finding, ensuring FAIL takes precedence when a finding matches both FAIL and
PASS requirements. Apply the same logic to the per-section counting to maintain
consistency.

In `@prowler/lib/outputs/compliance/ccc/ccc.py`:
- Around line 58-78: The issue is that effective_status varies per requirement,
allowing the same finding to be counted in both PASS and FAIL totals. Before
updating the muted_count, fail_count, and pass_count lists, you need to resolve
a single final status per finding that aggregates across all its requirements
and sections. Implement logic where a config-forced FAIL status overrides PASS
across all requirements for that finding, then use this resolved final status
(instead of the per-requirement effective_status) to update the overall counts.
The same resolved status should be determined once per finding before the
section iteration loop, ensuring each finding is counted only once in the
appropriate total.

In `@prowler/lib/outputs/compliance/universal/universal_table.py`:
- Around line 185-217: The current deduplication logic using finding index only
(in muted_count, fail_count, pass_count lists and group_seen dictionary) does
not account for the fact that effective_status now varies per requirement due to
per-requirement config status resolution. A single finding mapped to multiple
requirements can be counted with conflicting statuses. Either pre-compute a
single effective_status per finding by collapsing all its matched requirement
statuses with FAIL taking precedence before the group_key loop, or change the
deduplication keys to include req.id alongside the finding index to track status
per requirement instance instead of per finding.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b9a2fd2b-3eff-4efe-a516-4104b7c59721

📥 Commits

Reviewing files that changed from the base of the PR and between 48acb3b and 9cd1e92.

⛔ Files ignored due to path filters (61)
  • prowler/compliance/alibabacloud/cis_2.0_alibabacloud.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/alibabacloud/prowler_threatscore_alibabacloud.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/asd_essential_eight_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_account_security_onboarding_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_ai_security_framework_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_foundational_security_best_practices_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_foundational_technical_review_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_well_architected_framework_security_pillar_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/c5_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ccc_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_1.4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_1.5_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_2.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_3.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_4.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_5.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cis_6.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cisa_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ens_rd2022_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_20x_ksi_low_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_low_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_moderate_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ffiec_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/gdpr_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/gxp_21_cfr_part_11_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/gxp_eu_annex_11_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/hipaa_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/iso27001_2013_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/iso27001_2022_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/kisa_isms_p_2023_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/mitre_attack_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nis2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_171_revision_2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_53_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_53_revision_5_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_csf_1.1_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_csf_2.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/pci_3.2.1_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/pci_4.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/prowler_threatscore_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/rbi_cyber_security_framework_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/secnumcloud_3.2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/soc2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/c5_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/ccc_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/cis_4.0_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/cis_5.0_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/hipaa_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/nis2_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/secnumcloud_3.2_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/soc2_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/csa_ccm_4.0.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/dora_2022_2554.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/ccc_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.10_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.11_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.12_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.8_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/pci_4.0_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/prowler_threatscore_kubernetes.json is excluded by !prowler/compliance/**/*.json
📒 Files selected for processing (60)
  • prowler/CHANGELOG.md
  • prowler/lib/check/compliance_config_eval.py
  • prowler/lib/check/compliance_models.py
  • prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight.py
  • prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight_aws.py
  • prowler/lib/outputs/compliance/aws_well_architected/aws_well_architected.py
  • prowler/lib/outputs/compliance/c5/c5.py
  • prowler/lib/outputs/compliance/c5/c5_aws.py
  • prowler/lib/outputs/compliance/c5/c5_azure.py
  • prowler/lib/outputs/compliance/c5/c5_gcp.py
  • prowler/lib/outputs/compliance/ccc/ccc.py
  • prowler/lib/outputs/compliance/ccc/ccc_aws.py
  • prowler/lib/outputs/compliance/ccc/ccc_azure.py
  • prowler/lib/outputs/compliance/ccc/ccc_gcp.py
  • prowler/lib/outputs/compliance/cis/cis.py
  • prowler/lib/outputs/compliance/cis/cis_alibabacloud.py
  • prowler/lib/outputs/compliance/cis/cis_aws.py
  • prowler/lib/outputs/compliance/cis/cis_azure.py
  • prowler/lib/outputs/compliance/cis/cis_gcp.py
  • prowler/lib/outputs/compliance/cis/cis_github.py
  • prowler/lib/outputs/compliance/cis/cis_googleworkspace.py
  • prowler/lib/outputs/compliance/cis/cis_kubernetes.py
  • prowler/lib/outputs/compliance/cis/cis_m365.py
  • prowler/lib/outputs/compliance/cis/cis_oraclecloud.py
  • prowler/lib/outputs/compliance/cisa_scuba/cisa_scuba_googleworkspace.py
  • prowler/lib/outputs/compliance/ens/ens.py
  • prowler/lib/outputs/compliance/ens/ens_aws.py
  • prowler/lib/outputs/compliance/ens/ens_azure.py
  • prowler/lib/outputs/compliance/ens/ens_gcp.py
  • prowler/lib/outputs/compliance/generic/generic.py
  • prowler/lib/outputs/compliance/generic/generic_table.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_aws.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_azure.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_gcp.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_kubernetes.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_m365.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_nhn.py
  • prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp.py
  • prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp_aws.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_aws.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_azure.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_gcp.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_alibaba.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_aws.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_azure.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_gcp.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_kubernetes.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_m365.py
  • prowler/lib/outputs/compliance/universal/ocsf_compliance.py
  • prowler/lib/outputs/compliance/universal/universal_table.py
  • tests/lib/check/compliance_config_constraint_model_test.py
  • tests/lib/check/compliance_config_eval_test.py
  • tests/lib/check/compliance_config_requirements_data_test.py
  • tests/lib/outputs/compliance/cis/cis_aws_config_requirements_test.py
  • tests/lib/outputs/compliance/cis/cis_azure_config_requirements_test.py
  • tests/lib/outputs/compliance/ens/ens_aws_config_requirements_test.py
  • tests/lib/outputs/compliance/universal/ocsf_compliance_config_requirements_test.py
  • tests/lib/outputs/compliance/universal/universal_table_config_requirements_test.py

Comment thread prowler/lib/check/compliance_config_eval.py
Comment thread prowler/lib/check/compliance_config_eval.py Outdated
Comment thread prowler/lib/check/compliance_config_eval.py
Comment thread prowler/lib/check/compliance_models.py
Comment thread prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp.py Outdated
Comment thread prowler/lib/outputs/compliance/mitre_attack/mitre_attack.py Outdated
Comment thread tests/lib/check/compliance_config_constraint_model_test.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
prowler/lib/check/compliance_config_eval.py (1)

1-51: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Unknown Operators Should Fail Closed, Not Pass

Line 1-51 currently allows unknown operators in _check_operator to return True (per changed-range behavior), which lets malformed ConfigRequirements silently pass. That weakens the compliance guardrail and can produce false PASS outcomes.

💡 Proposed Fix
-    # unknown operator
-    return True
+    # unknown operator must fail closed
+    return False
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@prowler/lib/check/compliance_config_eval.py` around lines 1 - 51, The
_check_operator function currently returns True for unknown operators (at the
end of the function after all the if conditions), which allows malformed
ConfigRequirements to silently pass when they should fail. Change the final
return statement that handles unknown operators from return True to return False
so that any unrecognized operator causes the compliance requirement check to
fail conservatively instead of passing unsafely.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/developer-guide/security-compliance-framework.mdx`:
- Around line 484-485: The section header "## Configuration Guardrails for
Requirements" is missing the required VersionBadge component. Add the
<VersionBadge /> component immediately on the line following the section header
to indicate when this functionality was introduced in Prowler, as per the
documentation guidelines that require Version Badge components to be placed
directly after section headers for new features.

In `@prowler/lib/check/compliance_models.py`:
- Around line 339-341: The Provider field in the compliance model is not being
normalized or validated, which allows inconsistent values (different casing,
whitespace) to bypass constraint evaluation during exact string matching. Add a
field validator to the Provider field that normalizes the value by trimming
whitespace and converting to lowercase, ensuring consistent matching regardless
of input format. This should prevent silent constraint bypasses due to provider
name mismatches.

---

Outside diff comments:
In `@prowler/lib/check/compliance_config_eval.py`:
- Around line 1-51: The _check_operator function currently returns True for
unknown operators (at the end of the function after all the if conditions),
which allows malformed ConfigRequirements to silently pass when they should
fail. Change the final return statement that handles unknown operators from
return True to return False so that any unrecognized operator causes the
compliance requirement check to fail conservatively instead of passing unsafely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9c9cee60-8666-4562-99b5-13b398a20f37

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd1e92 and 6f17c87.

⛔ Files ignored due to path filters (2)
  • prowler/compliance/csa_ccm_4.0.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/dora_2022_2554.json is excluded by !prowler/compliance/**/*.json
📒 Files selected for processing (7)
  • docs/developer-guide/configurable-checks.mdx
  • docs/developer-guide/security-compliance-framework.mdx
  • prowler/lib/check/compliance_config_eval.py
  • prowler/lib/check/compliance_models.py
  • tests/lib/check/compliance_config_constraint_model_test.py
  • tests/lib/check/compliance_config_eval_test.py
  • tests/lib/check/compliance_config_requirements_data_test.py

Comment thread docs/developer-guide/security-compliance-framework.mdx
Comment thread prowler/lib/check/compliance_models.py Outdated
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.43497% with 73 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.85%. Comparing base (4e00cfd) to head (09dd0f8).
⚠️ Report is 3 commits behind head on master.

❗ There is a different number of reports uploaded between BASE (4e00cfd) and HEAD (09dd0f8). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (4e00cfd) HEAD (09dd0f8)
api 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #11669      +/-   ##
==========================================
- Coverage   94.12%   87.85%   -6.28%     
==========================================
  Files         247     1607    +1360     
  Lines       36629    54473   +17844     
==========================================
+ Hits        34477    47857   +13380     
- Misses       2152     6616    +4464     
Flag Coverage Δ
api ?
prowler-py3.10-aws 90.15% <ø> (?)
prowler-py3.10-azure 89.84% <ø> (?)
prowler-py3.10-external 78.40% <10.02%> (?)
prowler-py3.10-gcp 90.26% <ø> (?)
prowler-py3.10-kubernetes 89.94% <ø> (?)
prowler-py3.10-lib 87.84% <84.43%> (?)
prowler-py3.10-m365 90.07% <ø> (?)
prowler-py3.10-okta 90.27% <ø> (?)
prowler-py3.11-aws 90.16% <ø> (?)
prowler-py3.11-azure 89.69% <ø> (?)
prowler-py3.11-external 78.26% <10.02%> (?)
prowler-py3.11-gcp 90.13% <ø> (?)
prowler-py3.11-kubernetes 89.81% <ø> (?)
prowler-py3.11-lib 87.70% <84.43%> (?)
prowler-py3.11-m365 89.90% <ø> (?)
prowler-py3.11-okta 90.15% <ø> (?)
prowler-py3.12-aws 90.16% <ø> (?)
prowler-py3.12-azure 89.73% <ø> (?)
prowler-py3.12-external 78.33% <10.02%> (?)
prowler-py3.12-gcp 90.16% <ø> (?)
prowler-py3.12-kubernetes 89.84% <ø> (?)
prowler-py3.12-lib 87.77% <84.43%> (?)
prowler-py3.12-m365 89.99% <ø> (?)
prowler-py3.12-okta 90.18% <ø> (?)
prowler-py3.13-aws 90.15% <ø> (?)
prowler-py3.13-azure 89.84% <ø> (?)
prowler-py3.13-external 78.40% <10.02%> (?)
prowler-py3.13-gcp 90.27% <ø> (?)
prowler-py3.13-kubernetes 89.95% <ø> (?)
prowler-py3.13-lib 87.84% <84.43%> (?)
prowler-py3.13-m365 90.07% <ø> (?)
prowler-py3.13-okta 90.27% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
prowler 87.86% <86.04%> (∅)
api ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mintlify

mintlify Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
prowler 🟢 Ready View Preview Jun 23, 2026, 12:17 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/lib/check/compliance_config_eval_test.py`:
- Around line 312-318: The test_works_with_fail_pass_only_counts test method
needs an additional assertion to test the "Muted" status case. After the
existing calls to accumulate_group_status with "PASS" and "FAIL" statuses, add
another call to accumulate_group_status with "Muted" as the status parameter
(keeping the same group index of 0 and the existing counts and seen
dictionaries), then add an assertion to verify the expected behavior when a
"Muted" status is encountered on a counts dictionary that only has "FAIL" and
"PASS" keys. This will test the potential KeyError path in the
accumulate_group_status function and ensure proper coverage of the Muted-less
counts scenario.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7914b117-e6b0-49a9-afd0-a170ac496ba9

📥 Commits

Reviewing files that changed from the base of the PR and between 6f17c87 and 6036307.

📒 Files selected for processing (54)
  • prowler/lib/check/compliance_config_eval.py
  • prowler/lib/check/compliance_models.py
  • prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight.py
  • prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight_aws.py
  • prowler/lib/outputs/compliance/aws_well_architected/aws_well_architected.py
  • prowler/lib/outputs/compliance/c5/c5.py
  • prowler/lib/outputs/compliance/c5/c5_aws.py
  • prowler/lib/outputs/compliance/c5/c5_azure.py
  • prowler/lib/outputs/compliance/c5/c5_gcp.py
  • prowler/lib/outputs/compliance/ccc/ccc.py
  • prowler/lib/outputs/compliance/ccc/ccc_aws.py
  • prowler/lib/outputs/compliance/ccc/ccc_azure.py
  • prowler/lib/outputs/compliance/ccc/ccc_gcp.py
  • prowler/lib/outputs/compliance/cis/cis.py
  • prowler/lib/outputs/compliance/cis/cis_alibabacloud.py
  • prowler/lib/outputs/compliance/cis/cis_aws.py
  • prowler/lib/outputs/compliance/cis/cis_azure.py
  • prowler/lib/outputs/compliance/cis/cis_gcp.py
  • prowler/lib/outputs/compliance/cis/cis_github.py
  • prowler/lib/outputs/compliance/cis/cis_googleworkspace.py
  • prowler/lib/outputs/compliance/cis/cis_kubernetes.py
  • prowler/lib/outputs/compliance/cis/cis_m365.py
  • prowler/lib/outputs/compliance/cis/cis_oraclecloud.py
  • prowler/lib/outputs/compliance/cisa_scuba/cisa_scuba_googleworkspace.py
  • prowler/lib/outputs/compliance/ens/ens.py
  • prowler/lib/outputs/compliance/ens/ens_aws.py
  • prowler/lib/outputs/compliance/ens/ens_azure.py
  • prowler/lib/outputs/compliance/ens/ens_gcp.py
  • prowler/lib/outputs/compliance/generic/generic.py
  • prowler/lib/outputs/compliance/generic/generic_table.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_aws.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_azure.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_gcp.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_kubernetes.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_m365.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_nhn.py
  • prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp.py
  • prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp_aws.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_aws.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_azure.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_gcp.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_alibaba.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_aws.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_azure.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_gcp.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_kubernetes.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_m365.py
  • prowler/lib/outputs/compliance/universal/ocsf_compliance.py
  • prowler/lib/outputs/compliance/universal/universal_table.py
  • tests/lib/check/compliance_config_constraint_model_test.py
  • tests/lib/check/compliance_config_eval_test.py
  • tests/lib/outputs/compliance/universal/universal_table_config_requirements_test.py
💤 Files with no reviewable changes (40)
  • prowler/lib/outputs/compliance/asd_essential_eight/asd_essential_eight_aws.py
  • prowler/lib/outputs/compliance/c5/c5_azure.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_aws.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_kubernetes.py
  • prowler/lib/outputs/compliance/cis/cis_googleworkspace.py
  • prowler/lib/outputs/compliance/ccc/ccc_azure.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_nhn.py
  • prowler/lib/outputs/compliance/c5/c5_aws.py
  • prowler/lib/outputs/compliance/cis/cis_aws.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_m365.py
  • prowler/lib/outputs/compliance/cis/cis_alibabacloud.py
  • prowler/lib/outputs/compliance/ens/ens_aws.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_alibaba.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_azure.py
  • prowler/lib/outputs/compliance/cis/cis_azure.py
  • prowler/lib/outputs/compliance/ccc/ccc_gcp.py
  • prowler/lib/outputs/compliance/kisa_ismsp/kisa_ismsp_aws.py
  • prowler/lib/outputs/compliance/cis/cis_m365.py
  • prowler/lib/outputs/compliance/cisa_scuba/cisa_scuba_googleworkspace.py
  • prowler/lib/outputs/compliance/ccc/ccc_aws.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_gcp.py
  • prowler/lib/outputs/compliance/ens/ens_azure.py
  • prowler/lib/outputs/compliance/c5/c5_gcp.py
  • prowler/lib/outputs/compliance/cis/cis_kubernetes.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_kubernetes.py
  • prowler/lib/outputs/compliance/cis/cis_oraclecloud.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_m365.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_azure.py
  • prowler/lib/outputs/compliance/universal/ocsf_compliance.py
  • prowler/lib/outputs/compliance/cis/cis_github.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_aws.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_gcp.py
  • prowler/lib/outputs/compliance/generic/generic_table.py
  • prowler/lib/outputs/compliance/iso27001/iso27001_azure.py
  • prowler/lib/outputs/compliance/ens/ens_gcp.py
  • prowler/lib/outputs/compliance/mitre_attack/mitre_attack_gcp.py
  • prowler/lib/outputs/compliance/prowler_threatscore/prowler_threatscore_aws.py
  • prowler/lib/outputs/compliance/cis/cis_gcp.py
  • prowler/lib/outputs/compliance/aws_well_architected/aws_well_architected.py
  • prowler/lib/outputs/compliance/generic/generic.py

Comment thread tests/lib/check/compliance_config_eval_test.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@prowler/CHANGELOG.md`:
- Line 9: Update the PR number reference in the changelog entry from `#11667` to
`#11669` in the line describing the ConfigRequirements feature (the entry that
mentions "Per-requirement configuration validation for compliance frameworks via
`ConfigRequirements`"). Change both the PR number reference (`#11667`) and the
corresponding GitHub link URL to reflect the correct PR number (`#11669`).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3da0244d-2263-46b1-9cea-44c89de697e5

📥 Commits

Reviewing files that changed from the base of the PR and between 6036307 and 55d7971.

⛔ Files ignored due to path filters (1)
  • prowler/compliance/azure/hipaa_azure.json is excluded by !prowler/compliance/**/*.json
📒 Files selected for processing (5)
  • docs/developer-guide/security-compliance-framework.mdx
  • prowler/CHANGELOG.md
  • prowler/lib/check/compliance_config_eval.py
  • prowler/lib/check/compliance_models.py
  • tests/lib/check/compliance_config_eval_test.py

Comment thread prowler/CHANGELOG.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/lib/check/compliance_config_requirements_coverage_test.py`:
- Around line 208-211: The f-string prefix on the string literal
"_KEYS_NOT_AFFECTING_VERDICT:\n  " is unnecessary because there are no variable
interpolations within that string, which triggers flake8 F541. Remove the f
prefix from this string literal to resolve the linting error, keeping it as a
regular string while the rest of the concatenation with the join operation
remains unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2767c19-de54-4999-a42d-bf7834fafe5e

📥 Commits

Reviewing files that changed from the base of the PR and between 55d7971 and 179b09d.

⛔ Files ignored due to path filters (57)
  • prowler/compliance/alibabacloud/cis_2.0_alibabacloud.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/alibabacloud/prowler_threatscore_alibabacloud.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/alibabacloud/secnumcloud_3.2_alibabacloud.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/asd_essential_eight_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_ai_security_framework_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_foundational_security_best_practices_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_foundational_technical_review_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/aws_well_architected_framework_security_pillar_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/c5_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ccc_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/cisa_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ens_rd2022_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_20x_ksi_low_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_low_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/fedramp_moderate_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/ffiec_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/gdpr_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/gxp_21_cfr_part_11_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/hipaa_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/iso27001_2022_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/kisa_isms_p_2023_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/mitre_attack_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nis2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_171_revision_2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_53_revision_4_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_800_53_revision_5_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_csf_1.1_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/nist_csf_2.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/pci_3.2.1_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/pci_4.0_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/prowler_threatscore_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/rbi_cyber_security_framework_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/secnumcloud_3.2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/aws/soc2_aws.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/azure/c5_azure.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/csa_ccm_4.0.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/dora_2022_2554.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/c5_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/hipaa_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/mitre_attack_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/nis2_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/rbi_cyber_security_framework_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/secnumcloud_3.2_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/gcp/soc2_gcp.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/github/cis_1.0_github.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.10_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.11_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.12_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/cis_1.8_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/iso27001_2022_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/kubernetes/prowler_threatscore_kubernetes.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/m365/cis_4.0_m365.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/m365/cis_6.0_m365.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/m365/prowler_threatscore_m365.json is excluded by !prowler/compliance/**/*.json
  • prowler/compliance/okta/okta_idaas_stig_v1r2_okta.json is excluded by !prowler/compliance/**/*.json
📒 Files selected for processing (3)
  • tests/lib/check/compliance_config_requirements_coverage_baseline.json
  • tests/lib/check/compliance_config_requirements_coverage_test.py
  • tests/lib/outputs/compliance/iso27001/iso27001_aws_numeric_config_requirements_test.py

Comment thread tests/lib/check/compliance_config_requirements_coverage_test.py Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 24, 2026
Comment thread prowler/lib/check/compliance_models.py Fixed
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compliance Issues/PRs related with the Compliance Frameworks documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants