Get started with CEL
Common Expression Language (CEL) is an expression language used by Sophos XDR automations. You can use CEL to manipulate data in connectors, playbook templates, playbook triggers, and playbook inputs. For more information, see the official Google CEL documentation.
Usage
CEL expressions use the ${} syntax. In playbook templates and trigger filters, ${} is optional. Note that the ${} syntax must be used when authoring connector definitions.
Example
Expression:
${'Hello World'}
Output:
Hello World
For more examples, see CEL examples.
Data types
CEL is strongly-typed and supports the following data types:
| Data Type | Description | Example |
|---|---|---|
int | 64-bit signed integers | |
uint | 64-bit unsigned integers | |
double | 64-bit IEEE floating-point numbers | |
bool | Booleans (true or false) | |
string | Strings of Unicode code points | |
bytes | Byte sequences | |
list | Lists of values | [1,2,3] |
map | Associative arrays with int, uint, bool, or string keys | {'key':'value'} |
null_type | The value null | |
| message names | Protocol buffer messages | |
type | Values representing the types in the first column | string |
In many cases, a data type can be converted using built-in macros: int(), uint(), double(), string(), list(), map(), bool(), bytes().
Convert a number to a string.
Expression:
${ string(8) }
Output:
8
Expression:
${ type(string(8)) }
Output:
string
In most cases, defining the value of a variable also sets the data type:
Example
Expression:
${ {'key':'value'} }
Output:
a map data type, with a single key called "key" and a value of "value"
Expression:
${ [1,2,3] }
Output:
a list data type, with the values 1, 2, and 3
Expression:
${ [] }
Output:
an empty list
Expression:
${ 'this is a string' }
Output:
this is a string
Accessing data
You can access data by referencing the variable name.
Example
Expression:
${myvar}
You can access data in a map in either of the following ways. Both expressions return the same result.
Example
Expression:
${map_var.map_key}
Expression:
${map_var['map_key']}
Output:
the value associated with the key map_key in the map_var map variable
List elements can be accessed if you know the element order (zero-based).
Example
Expression:
${mylist[0]}
Output:
the first value in `mylist`
Conditionals
CEL doesn't support a traditional if, then, else statement. Instead, it uses a ternary conditional in the following format: <if> ? <then> : <else>.
<if>: Any expression that evaluates to a true/false boolean value.<then>: Can be any expression and will be returned if the condition is true.<else>: Can be any expression and will be returned if the condition is false.
The data type of the <then> and <else> values must match.
Example
Expression:
${ int_val > 3 ? 'int_val is greater than 3' : 'int_val is less than 3' }
Output (int_val=4):
int_val is greater than 3
Output (int_val=2):
int_val is less than 3
Macros
A number of macros are supported that extend the functionality of the language. Macros typically only apply to and accept specific data types. For example, the toLower() macro applies to a string or a list.
Example
Expression:
${'Hello World'.toLower()}
Output:
hello world
Expression:
${toLower(['Hello World'])}
Output:
[
hello world
]
For a list of common supported macros, see Common supported CEL macros.
Avoiding errors
Attempting to access a variable that is not defined results in a no_such_field error. You can avoid this by using the has() macro with a ternary conditional.
Example
Expression:
${ has(map_var, 'map_key') ? map_var.map_key : '' }
Output:
the value of map_var.map_key if it exists, else an empty string
Another common error is due to mismatched type values. You may need to convert the data in a variable to a specific data type to prevent this issue, such as in the following example.
Example
Expression:
${ int(int_val) }
Output:
the value of int_val as an integer type