Skip to content

Commit 7c339ed

Browse files
authored
docs(mutelist): fix misleading docstrings about tag and exception logic (#9205)
1 parent be0b8bb commit 7c339ed

File tree

2 files changed

+118
-17
lines changed

2 files changed

+118
-17
lines changed

docs/user-guide/cli/tutorials/mutelist.mdx

Lines changed: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,39 @@ The Mutelist option works in combination with other filtering mechanisms and mod
1919

2020
## How the Mutelist Works
2121

22-
The **Mutelist** uses both "AND" and "OR" logic to determine which resources, checks, regions, and tags should be muted. For each check, the Mutelist evaluates whether the account, region, and resource match the specified criteria using "AND" logic. If tags are specified, the Mutelist can apply either "AND" or "OR" logic.
22+
The **Mutelist** uses **AND logic** to evaluate whether a finding should be muted. For a finding to be muted, **ALL** of the following conditions must match:
2323

24-
If any of the criteria do not match, the check is not muted.
24+
- **Account** matches (exact match or `*`)
25+
- **Check** matches (exact match, regex pattern, or `*`)
26+
- **Region** matches (exact match, regex pattern, or `*`)
27+
- **Resource** matches (exact match, regex pattern, or `*`)
28+
- **Tags** match (if specified)
29+
30+
If **any** of these criteria do not match, the finding is **not muted**.
31+
32+
### Tag Matching Logic
33+
34+
Tags have special matching behavior:
35+
36+
- **Multiple tags in the list = AND logic**: ALL tags must be present on the resource
37+
```yaml
38+
Tags:
39+
- "environment=dev"
40+
- "team=backend" # BOTH tags required
41+
```
42+
43+
- **Regex alternation within a single tag = OR logic**: Use the pipe operator `|` for OR
44+
```yaml
45+
Tags:
46+
- "environment=dev|environment=stg" # Matches EITHER dev OR stg
47+
```
48+
49+
- **Complex tag patterns**: Combine AND and OR using regex
50+
```yaml
51+
Tags:
52+
- "team=backend" # Required
53+
- "environment=dev|environment=stg" # AND (dev OR stg)
54+
```
2555

2656
<Note>
2757
Remember that mutelist can be used with regular expressions.
@@ -40,9 +70,10 @@ The Mutelist file uses the [YAML](https://en.wikipedia.org/wiki/YAML) format wit
4070
```yaml
4171
### Account, Check and/or Region can be * to apply for all the cases.
4272
### Resources and tags are lists that can have either Regex or Keywords.
43-
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
44-
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
45-
### For each check you can except Accounts, Regions, Resources and/or Tags.
73+
### Multiple tags in the list are "ANDed" together (ALL must match).
74+
### Use regex alternation (|) within a single tag for "OR" logic (e.g., "env=dev|env=stg").
75+
### For each check you can use Exceptions to unmute specific Accounts, Regions, Resources and/or Tags.
76+
### All conditions (Account, Check, Region, Resource, Tags) are ANDed together.
4677
########################### MUTELIST EXAMPLE ###########################
4778
Mutelist:
4879
Accounts:
@@ -148,11 +179,11 @@ Mutelist:
148179
149180
| Field| Description| Logic
150181
|----------|----------|----------
151-
| `account_id`| Use `*` to apply the mutelist to all accounts.| `ANDed`
152-
| `check_name`| The name of the Prowler check. Use `*` to apply the mutelist to all checks, or `service_*` to apply it to all service's checks.| `ANDed`
153-
| `region`| The region identifier. Use `*` to apply the mutelist to all regions.| `ANDed`
154-
| `resource`| The resource identifier. Use `*` to apply the mutelist to all resources.| `ANDed`
155-
| `tag`| The tag value.| `ORed`
182+
| `account_id`| Use `*` to apply the mutelist to all accounts. Supports exact match or wildcard.| `AND` (with other fields)
183+
| `check_name`| The name of the Prowler check. Use `*` to apply the mutelist to all checks, or `service_*` to apply it to all service's checks. Supports regex patterns.| `AND` (with other fields)
184+
| `region`| The region identifier. Use `*` to apply the mutelist to all regions. Supports regex patterns.| `AND` (with other fields)
185+
| `resource`| The resource identifier. Use `*` to apply the mutelist to all resources. Supports regex patterns.| `AND` (with other fields)
186+
| `tags`| List of tag patterns in `key=value` format. **Multiple tags = AND** (all must match). **Regex alternation within single tag = OR** (use `tag1\|tag2`).| `AND` between tags, `OR` within regex
156187

157188
### Description
158189

@@ -173,6 +204,68 @@ Replace `<provider>` with the appropriate provider name.
173204
- The Mutelist can be used in combination with other Prowler options, such as the `--service` or `--checks` option, to further customize the scanning process.
174205
- Make sure to review and update the Mutelist regularly to ensure it reflects the desired exclusions and remains up to date with your infrastructure.
175206

207+
## Current Limitations and Workarounds
208+
209+
### Limitation: No OR Logic Between Different Rule Sets
210+
211+
The current Mutelist schema **does not support OR logic** between different condition sets. Each check can have only **one rule object**, and all conditions are **ANDed** together.
212+
213+
**Example of unsupported scenario:**
214+
```yaml
215+
# ❌ INVALID: Cannot have multiple rule blocks for the same check
216+
Accounts:
217+
"*":
218+
Checks:
219+
"*": # Rule 1
220+
Regions: ["eu-west-1", "us-west-2"]
221+
Resources: ["*"]
222+
"*": # Rule 2 - This will OVERWRITE Rule 1 (YAML duplicate key)
223+
Regions: ["us-east-1"]
224+
Tags: ["environment=dev"]
225+
```
226+
227+
**Workaround: Use multiple scans with different mutelists**
228+
229+
For complex scenarios requiring OR logic, run separate scans:
230+
231+
```bash
232+
# Scan 1: Mute findings in non-critical regions
233+
prowler aws --mutelist-file mutelist_noncritical.yaml
234+
235+
# Scan 2: Mute dev/stg in critical regions
236+
prowler aws --mutelist-file mutelist_critical.yaml --regions us-east-1,sa-east-1
237+
```
238+
239+
Then merge the outputs in your reporting pipeline.
240+
241+
### Limitation: Cannot Negate Regions
242+
243+
You cannot express "all regions **except** X and Y". You must explicitly list all regions you want to mute.
244+
245+
**Workaround:**
246+
```yaml
247+
# Must enumerate all unwanted regions
248+
Accounts:
249+
"*":
250+
Checks:
251+
"*":
252+
Regions:
253+
- "af-south-1"
254+
- "ap-east-1"
255+
# ... list all regions EXCEPT the ones you want to monitor
256+
Resources: ["*"]
257+
```
258+
259+
### Best Practices
260+
261+
1. **Use regex patterns for flexibility**: Instead of listing multiple resources, use regex patterns like `"dev-.*"` or `"test-instance-[0-9]+"`
262+
263+
2. **Combine tag OR logic with regex**: Use `"environment=dev|environment=stg|environment=test"` instead of multiple tag entries
264+
265+
3. **Be specific with exceptions**: Use the `Exceptions` field to unmute specific resources within a broader muting rule
266+
267+
4. **Test your mutelist**: Run Prowler with `--output-modes json` and verify that the expected findings are muted
268+
176269
## AWS Mutelist
177270

178271
### Muting specific AWS regions

prowler/lib/mutelist/mutelist.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,10 @@ def is_muted(
153153
Check if the provided finding is muted for the audited account, check, region, resource and tags.
154154
155155
The Mutelist works in a way that each field is ANDed, so if a check is muted for an account, region, resource and tags, it will be muted.
156-
The exceptions are ORed, so if a check is excepted for an account, region, resource or tags, it will not be muted.
157-
The only particularity is the tags, which are ORed.
156+
157+
Exceptions use AND logic across specified fields, with unspecified fields treated as wildcards (matching all values).
158+
159+
Tag matching uses AND logic when multiple tags are listed (all must match). OR logic is achieved using regex alternation (|) within a single tag pattern.
158160
159161
So, for the following Mutelist:
160162
```
@@ -167,11 +169,16 @@ def is_muted(
167169
Resources:
168170
- 'i-123456789'
169171
Tags:
170-
- 'Name=AdminInstance | Environment=Prod'
172+
- 'Name=AdminInstance|Environment=Prod'
171173
Description: 'Field to describe why the findings associated with these values are muted'
172174
```
173175
The check `ec2_instance_detailed_monitoring_enabled` will be muted for all accounts and regions and for the resource_id 'i-123456789' with at least one of the tags 'Name=AdminInstance' or 'Environment=Prod'.
174176
177+
Note: The pipe (|) in the tag pattern provides OR logic via regex alternation. To require BOTH tags, use two separate tag entries:
178+
Tags:
179+
- 'Name=AdminInstance'
180+
- 'Environment=Prod'
181+
175182
Args:
176183
mutelist (dict): Dictionary containing information about muted checks for different accounts.
177184
audited_account (str): The account being audited.
@@ -408,12 +415,13 @@ def is_item_matched(matched_items, finding_items, tag=False) -> bool:
408415
Args:
409416
matched_items (list): List of items to be matched.
410417
finding_items (str): String to search for matched items.
411-
tag (bool): If True the search will have a different logic due to the tags being ANDed or ORed:
412-
- Check of AND logic -> True if all the tags are present in the finding.
413-
- Check of OR logic -> True if any of the tags is present in the finding.
418+
tag (bool): If True, uses AND logic across multiple tags in the list.
419+
- Multiple tags: ALL tags in matched_items must be present in finding_items (AND logic).
420+
- Single tag with regex alternation (|): Matches if pattern is found (enables OR within pattern).
421+
- For non-tags: Uses OR logic - returns True if ANY item matches.
414422
415423
Returns:
416-
bool: True if any of the matched_items are present in finding_items, otherwise False.
424+
bool: For tags - True if ALL patterns match. For non-tags - True if ANY pattern matches.
417425
"""
418426
try:
419427
is_item_matched = False

0 commit comments

Comments
 (0)