Modifying Detections with Inline Filters
Modify an existing rule without writing code
Last updated
Modify an existing rule without writing code
Last updated
Inline filters are in open beta as of Panther version 1.54. Please share any bug reports and feature requests with your account team.
You can easily tune existing rules, including Panther-managed rules, by adding Inline Filters. An Inline Filter is a condition that must pass in order for the detection logic to then be run. Inline Filters are available only on rules, not scheduled rules nor policies.
In the Panther Console, you can create Inline Filters using a no-code builder. In the CLI workflow, you can create Inline Filters by adding the InlineFilters
YAML key.
A common use case for filters is to add an allowlist or denylist.
Filter statements are evaluated before a detection's logic. A filter must return true
(i.e., match the event) for the detection logic itself to then be run.
In both the Console and CLI workflow, filters can be grouped using AND
or OR
logic.
If an event does not contain the field the filter is evaluating, the filter will pass. If the field the filter is evaluating has a value of none
, the filter will return false
on positive comparators or on comparators that don't apply, and true
for inverse comparators.
In the Console, filters are not available during new rule creation. In the CLI workflow, you can include InlineFilters
on new rules.
While it is broadly discouraged to manage detection content using both CLI workflows and the Console simultaneously, it is possible to use Inline Filters in the Console alongside the CLI workflow. Filters created in the Console will not be overwritten or deleted when an update to detection content is made in the CLI workflow.
You can add filters to a rule from its edit page, or within an alert triggered by that rule.
In the left-hand navigation bar of your Panther Console, click Detections.
In the list of detections, click a rule's name to view its details page.
Within the Detect section, under Filter to only include events: and to the right of Where, click +.
In the menu that appears, select either Add Filter or Add Filter Group.
For each filter (either on its own or within a group), define the logic:
Click Key, then select an event key the condition will apply to.
To indicate a nested field, use JSON path notation.
Some options may include [*]
, indicating the key is an array of objects. Learn more about indexing an array of objects below.
Click Condition, then select a condition.
If the selected Condition requires an inputted value(s) (e.g., is
or contains
), provide a value or list of values.
If the values(s) field takes in an array, see the Inputting array values instructions below.
Between each filter and filter group, ensure the correct combinator (either and or or) is selected.
Run unit tests to ensure they pass with the added filter(s).
In the upper-right corner of the page, click Deploy to save your changes.
If the Rule Filter operator you've selected requires the value field to take in an array (such as the is in
operator), you'll input the array values in a modal that pops up when you click into the value field.
To add values to an array:
After selecting a Key and Condition for your Filter, click into the values field.
This will open the array input modal.
In the modal, enter the array value(s) in the input field.
If your input is comma-delimited, check the Values entered above are comma-delimited checkbox.
When this field is checked, the text inputted into the values field will be separated (using a comma delimiter) into multiple values. For example, entering "User 1,User 2,User 3" will result in three values added.
If your input is not comma-delimited, leave Values entered above are comma-delimited unchecked.
Click Add.
Repeat steps 2-3 as needed, until all values have been added to the array.
Click Apply.
While creating a filter expression, if there is an event key whose value is an array of objects, that key will be shown in the dropdown selector with the array indexing symbol [*]
, along with the fields in the object. You can use [*]
to target the selected field in all objects in the array, or replace *
with an integer to index the array, targeting a single field.
It will be represented in the event field selector as:
By default, Panther applies a wildcard array index ([*]
) that will search across values for the chosen field in all objects in the array. When [*]
is used, an array of these values is created and searched. Because of this, only the array conditions are available: is empty
, is not empty
, contains
, does not contain
.
For example, the below filter expression (resources[*].type
contains
AWS::IAM::Role
) means an event will match if any value of type
in the resources
array is AWS::IAM::Role
.
However, you can replace the *
with an integer to index the array, which specifies a single object in the array. In this case, Panther will only evaluate the value of the nested field at that index.
The conditions shown will be updated to those which are applicable to the data type of the nested field chosen:
In addition to creating no-code rule filters in the Panther Console, you can also create YAML filters on your rules written as Simple Detections or Python detections.
Like the filters created in the Console, YAML filters are evaluated before the detection logic of a rule. If the filter returns true
, the detection logic will be executed. If the filter returns false
, the evaluation of the detection will stop, and the detection will return false
altogether.
InlineFilter
syntaxA YAML filter is denoted by the InlineFilters
key. Within InlineFilters
, list one or more match expressions. See Simple Detection Match Expression Reference to learn how to construct different types of match expressions.
Example:
Some match expression functionality described in Simple Detection Match Expression Reference is not possible in InlineFilters
. These limitations include:
InlineFilters
cannot be used on scheduled rules or policies, only rules.
The following match expression types cannot be used within InlineFilters
:
The Key
and DeepKey
key specifiers cannot be used within InlineFilters
—only KeyPath
may be used.
The OnlyOne
and None
combinators cannot be used within InlineFilters
—only All
and Any
may be used.
Many Condition
values cannot be used within InlineFilters
. Only the following values may be used:
Equals
DoesNotEqual
IsGreaterThan
IsGreaterThanOrEquals
IsLessThan
IsLessThanOrEquals
Contains
DoesNotContain
StartsWith
EndsWith
IsIPAddressInCIDR
IsIPAddressNotInCIDR
CIDRContainsIPAddresses
CIDRDoesNotContainIPAddresses
IsIn
IsNotIn
IsIPAddressPublic
IsIPAddressPrivate
IsNullOrEmpty
IsNotNullOrEmpty
To create an Inline Filter in the CLI workflow on a rule created as either a Python or Simple Detection, in the detection's YAML file, include the InlineFilters
key. Within InlineFilters
, include one or more match expressions.
For Panther-managed rules with filters, you currently cannot add or edit unit tests. You cannot save a rule if the unit test does not pass.
If a unit test fails, take the following steps:
Clone the Panther-managed rule.
Add your filter(s) to the cloned rule.
Edit the unit tests for the cloned rule so that they pass.
Refer to the below operators and value types when building out your filters in the Console.
Operation | Usage guidelines | Supported field types | Examples |
---|---|---|---|
is / is not | An event will match when the field matches/does not match the value in the filter | string, ip, bool, int | username is “root” |
is in / is not in | An event will match when the field matches/does not match an entry in the list of values in the filter | string, int | username is in [ “root”, “admin” ] port is in [25, 553] |
is empty | An event will match when the field's value is not specified. The operator tests only for the absence of data | string, int array, ip array, float array, bool array, string array | errors_list is empty |
is not empty | An event will match when the field's value is specified. The operator tests only for the presence of data | string, int array, ip array, float array, bool array, string array | errors_list is not empty |
contains | An event will match when the value of the field specified contains the value provided When the event value is a string or a string array, partial matching is supported | string, int array, ip array, bool array, string array | domain contains “.google.com” p_any_port contains 22 |
does not contain | An event will match when the value of the field specified does not contain the value provided When the event value is a string or a string array, partial matching is supported | string, int array, ip array, bool array, string array | domain !contains “.google.com” p_any_port !contains 22 |
starts with | An event will match when the value of the field specified begins with the value provided | string | role starts with “admin_” |
ends with | An event will match when the value of the field specified ends with the value provided | string | domain ends with “.cc” |
is greater than | An event will match when the field's value is greater than the value provided in the filter | int, float | port > 1023 |
is less than | An event will match when the field's value is less than the value provided in the filter | int, float | port < 1024 |
is greater than or equal | An event will match when the field's value is greater than or equal to the value provided in the filter | int | count ≥ 1 |
is less than or equal | An event will match when the field's value is less than or equal to the value provided in the filter | int | count ≤ 100 |
is private | An event will match when the IP address specified is private | IP | dst_ip is_private |
is public | An event will match when the IP address specified is public | IP | src_ip is_public |
is in CIDR / is not in CIDR | An event will match when the IP address specified is/is not within a provided CIDR (Classless Inter-Domain Routing) block | IP | src_ip in_cidr 192.168.0.0/16 |
does not contain IP in CIDR | An event will match when the IP array specified does not contain any IP address within the CIDR block provided | ip array | p_any_ip_address !contains_ip 8.8.0.0/16 p_any_ip_address !contains_ip 1.1.1.1/32 |
contains IP in CIDR | An event will match when the IP array specified contains an IP address within the CIDR block provided | ip array | p_any_ip_address contains_ip 8.8.0.0/16 p_any_ip_address contains_ip 1.1.1.1/32 |
Value types | Description |
---|---|
| A string value |
| A 32-bit integer number in the range |
| A 64-bit floating point number |
| A boolean value |
| A JSON array where each element is of the same type |
| A single valid IPv4 or IPv6 address |
| A classless inter-domain routing block |
When this field is unchecked, you can add values that contain commas one at a time. For example, entering "1,000" will add just one value.
For example, take this resources
field in the AWS.CloudTrail
schema: