Skip to content

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