Condition Syntax

A condition is a boolean expression related to a single event that has been detected by Falco. You can use fields related to every supported event, but this document focuses on syscalls as they're currently the most common. The language supports boolean operators and parentheses as you'd expect. For example a condition like:

evt.type = execve and evt.dir = < and (proc.name = cat or proc.name = grep)

This will trigger for each execution of cat or grep. Below you can take a closer look at what is the meaning of those fields such as evt.dir, how to discover the types of events available, and which fields are present with which event type.

Syscall event types, direction and args

Every syscall event will present the evt field class. Each condition that you write for those events will normally start with a evt.type expression or macro; this makes a lot of sense since security rules normally consider one syscall type at a time. For instance, you may want to consider open or openat to catch suspicious activity when opening files, execve to inspect spawned processes, and so forth. You don't have to guess the syscall name, as you can see the complete list of supported system calls events and understand which ones you can use.

Every syscall has an entry event and an exit event which is shown in the evt.dir field, also known as the "direction" of the system call. A value of > indicates entry, which fires when the syscall is invoked, while < marks exit, meaning that the call has returned. In fact, by looking at the supported system call list you can see that our events have both entries. For example:

> setuid(UID uid)
< setuid(ERRNO res)

Most of the time the engine informs you about exit events as you want to understand what happened after the event execution is complete. You can see by using the events associated with opening files.

> open()
< open(FD fd, FSPATH name, FLAGS32 flags, UINT32 mode, UINT32 dev)
> openat()
< openat(FD fd, FD dirfd, FSRELPATH name, FLAGS32 flags, UINT32 mode, UINT32 dev)

As you can see, each event has a list of arguments associated with it that you can access by using evt.arg.<argname>. For example, to identify when a process opens a file to overwrite it, you need to check if the list of flags contains O_TRUNC. You can use the evt.arg.flags field of the open and openat exit events shown above and the rule will then look like this:

evt.type in (open, openat) and evt.dir = < and evt.arg.flags contains O_TRUNC

Note that the arguments do not necessarily match the raw parameters that are used in the Linux kernel, but are parsed by Falco to make it easier to write rules. By using the evt fields we can inspect many more aspects that are common across events.

Syscall event context and metadata

While the evt fields allow you to write pretty expressive conditions, arguments and common fields are usually not enough to write full security rules. Many times you want to add conditions based on the process context the event happens in, or whether or not something is happening inside a container or even correlate each event with the relevant Kubernetes metadata for the cluster, pods, and more. For this reason, Falco enriches many events with other field classes. Not all the classes are available for all the events and the list can grow. The documentation for each clarifies when those are expected to be available, but some are so common that you often rely on them.

The proc field class gives you the context about the process and thread that is generating a specific syscall. This information is usually very important. The most basic piece of information you can get out of it is proc.name and proc.pid, but you can even traverse the process hierarchy by using proc.aname[<n>] and proc.apid[<n>]. Likewise, you may be interested in which user performs a specific action via the user field class.

The documentation gives you an example of how to catch executions of bash within containers:

if evt.type = execve and evt.dir = < and container.id != host and proc.name = bash

Note that you don't even have to look at the execve args. That is because once execve has returned the process context recorded by Falco is updated, meaning that the proc. fields will already refer to all information, including the command line, executable, arguments, related to the new process that was just spawned.

Operators

You can use the following operators in conditions:

OperatorsDescription
=, !=Equality and inequality operators.
<=, <, >=, >Comparison operators for numeric values.
contains, icontainsFor strings will evaluate to true if a string contains another, and icontains is the case insensitive version. For flags it will evaluate to true if the flag is set. Examples: proc.cmdline contains "-jar", evt.arg.flags contains O_TRUNC.
startswith, endswithCheck prefix or suffix of strings.
globEvaluate standard glob patterns. Example: fd.name glob "/home/*/.ssh/*".
in, intersectsSet operations.
pmatchCompare a file path against a set of file or directory prefixes. Example: fd.name pmatch (/tmp/hello) will evaluate to true against /tmp/hello, /tmp/hello/world but not /tmp/hello_world.
existsCheck if a field is set. Example: k8s.pod.name exists.
bcontains, bstartswithThese operators work similarly to contains and startswith and allow performing byte matching against a raw string of bytes, accepting as input a hexadecimal string. Examples: evt.buffer bcontains CAFEBABE, evt.buffer bstartswith 012AB3CC.