arrayfilter - Reference Guide - Cortex XDR - Cortex - Security Operations

Cortex XDR XQL Language Reference

Product
Cortex XDR
Creation date
2024-07-16
Last date published
2024-09-25
Category
Reference Guide
Abstract

Learn more about the Cortex Query Language arrayfilter() function.

Syntax

arrayfilter(<array>, <condition>)
arrayfilter(<array>, "@element"<operator>"<array element>")

Note

The <operator> can be any of the ones supported, such as = and !=.

Description

The arrayfilter() function returns a new array with the elements which meet the given condition. The function does this by filtering the results of an array in one of the following ways:

  • Returns the results when a certain condition is applied to the array.

  • Returns the results when a particular array is set to a specified array element.

Though it's possible to define the arrayfilter() function with any condition, the examples below focus on conditions using the @element that are based on the current element being tested.

When the dfe_labels array is not empty, use the Alter stage to assign a value to a field called x that returns the value of the arrayfilter function. The arrayfilter function filters the dfe_labels array for the array element set to network.

dataset = xdr_data 
| filter dfe_labels != null
| alter x = arrayfilter(dfe_labels , "@element" = "network") 
| fields x, dfe_labels 
| limit 100 

This queries below illustrate how to check whether any IPs are included or not included in the blocked list called CIDRS. The Query Results tables are also included to help explain what happens as the arrayfilter() function is slightly modified.

This query returns results for each IP that don't match anything in the CIDRS array blocked list:

dataset = xdr_data
| limit 1
| alter cidrs = arraycreate("10.0.0.0/8","172.16.0.0/16"), ip = arraycreate("192.168.1.1", "172.16.20.18")
| fields cidrs, ip
| arrayexpand ip
| alter non_matching_cidrs = arrayfilter(cidrs, ip not incidr "@element")

Results:

The following table details for each IP the logic that is first performed before the final results for the query are displayed:

IP

Statement

TRUE/FALSE

192.168.1.1

not in 10.0.0.0/8

TRUE

192.168.1.1

not in 172.16.0.0/16

TRUE

172.16.20.18

not in 10.0.0.0/8

TRUE

172.16.20.18

not in 172.16.0.0/16

FALSE

For each IP, an array of CIDRS is returned in the NON_MATCHING_CIDRS column, which doesn't match the CIDRS array. In addition, from the above table, arrayfilter() only returns anything that resolves as TRUE. This explains the query results displayed in the following table:

IP

CIDRS

NON_MATCHING_CIDRS

192.168.1.1

10.0.0.0/8,172.16.0.0/16

10.0.0.0/8,172.16.0.0/16

172.16.20.18

10.0.0.0/8,172.16.0.0/16

10.0.0.0/8

Now, let's update the query to return results for each IP that match anything in the CIDRS array:

dataset = xdr_data
| limit 1
| alter cidrs = arraycreate("10.0.0.0/8","172.16.0.0/16"), ip = arraycreate("192.168.1.1", "172.16.20.18")
| fields cidrs, ip
| arrayexpand ip
| alter matching_cidrs = arrayfilter(cidrs, ip incidr "@element")

Results:

The following table details for each IP the logic that is first performed before the final results for the query are displayed:

IP

Statement

TRUE/FALSE

192.168.1.1

in 10.0.0.0/8

FALSE

192.168.1.1

in 172.16.0.0/16

FALSE

172.16.20.18

in 10.0.0.0/8

FALSE

172.16.20.18

in 172.16.0.0/16

TRUE

For each IP, an array of CIDRS is returned in the MATCHING_CIDRS column, which matches the CIDRS array. In addition, from the above table, arrayfilter() only returns anything that resolves as TRUE. This explains the query results displayed in the following table:

IP

CIDRS

MATCHING_CIDRS

192.168.1.1

10.0.0.0/8,172.16.0.0/16

empty array

172.16.20.18

10.0.0.0/8,172.16.0.0/16

172.16.0.0/16