Falco isn’t just another security tool; it’s a runtime threat detection engine that transforms your containerized applications into self-auditing systems, surfacing suspicious activity by analyzing system calls.

Let’s see it in action. Imagine you have a Kubernetes cluster and you want to detect if any pod tries to establish an outbound connection to a known malicious IP address.

First, you need to install Falco. The easiest way is often with its Helm chart:

helm install falco falco-charts/falco --namespace falco --create-namespace

Once installed, Falco starts monitoring your Kubernetes nodes. Its power comes from its rules. Here’s a simplified rule that triggers on outbound connections to a specific IP:

- rule: Outbound connection to known malicious IP
  desc: Detect an outbound connection to a known malicious IP address.
  condition: outbound and fd.sport=80 and fd.sip="192.0.2.1"
  output: Outbound connection to a malicious IP detected (user: %user.name, proc: %proc.name, fd.sip: %fd.sip)
  priority: CRITICAL

Now, let’s simulate this. If a pod running a web server on your cluster tries to connect to 192.0.2.1 on port 80, Falco will fire an alert. You’ll see this in your Falco output (which can be configured to go to stdout, a file, or a SIEM):

10:30:01.123456789: Critical: Outbound connection to known malicious IP detected (user: nobody, proc: curl, fd.sip: 192.0.2.1)

This event means Falco intercepted a system call (like connect(2)) initiated by the curl process (running as user nobody inside a container) attempting to reach 192.0.2.1 on port 80. The outbound condition checks the direction of the connection, and fd.sip specifically targets the destination IP.

Falco operates by tapping into the kernel’s system call interface. On Linux, this is typically done via a kernel module or, for more flexibility and compatibility, using eBPF. When an event occurs in the kernel (like a process opening a file, executing a program, or making a network connection), Falco’s engine receives this event. It then compares the event’s attributes against its configured rules. If a rule’s condition matches the event, Falco triggers the associated output and priority.

The magic is in the condition syntax. It’s a powerful DSL (Domain Specific Language) that allows you to define complex patterns. You can combine event types (openat, execve, connect) with properties of the process (proc.name, proc.args, user.name), the file (fd.name, fd.type), the network connection (fd.sip, fd.sport, fd.proto), and even the container environment (container.id, container.name, k8s.ns.name).

For example, a more sophisticated rule might detect a shell process (proc.name=sh or proc.name=bash) being executed inside a container that’s not supposed to have shell access, especially if it’s trying to write to sensitive directories:

- rule: Suspicious shell in container
  desc: Detect shell execution in containers, especially if writing to sensitive paths.
  condition: container and proc.name in (sh, bash, zsh) and evt.type=execve and fd.name contains /etc/passwd
  output: Suspicious shell process %proc.name executed in container %container.name (PID: %thread.tid) writing to sensitive file %fd.name.
  priority: WARNING

This rule looks for any shell process (proc.name in (sh, bash, zsh)) that is executed (evt.type=execve) within a container (container) and is attempting to access (fd.name contains) the /etc/passwd file. The container macro is a convenience that expands to container.id != host.

The exact levers you control are primarily the rules themselves. Falco’s rule language is extensive. You can craft rules to detect:

  • Privilege Escalation: A process trying to setuid or setgid to root from a non-root user.
  • Unusual Network Activity: A web server process attempting to bind to a privileged port (<1024).
  • File Integrity Monitoring: A configuration file (/etc/ssh/sshd_config) being modified.
  • Container Escapes: A process within a container trying to access host file system paths (e.g., /proc, /dev).
  • Malware Signatures: Specific command-line arguments or executable names associated with known threats.

The truly powerful aspect of Falco’s rule engine is its ability to correlate events across time and different system calls. You can build rules that trigger not just on a single event, but on a sequence or pattern of events. For instance, detecting a web server process (proc.name=nginx) that suddenly starts executing (evt.type=execve) a script from a temporary directory (fd.directory=/tmp) after receiving a network request.

Falco’s flexibility extends to its output and integration. You can configure it to send alerts to standard output, a file, syslog, or directly to a SIEM system like Splunk or Elasticsearch via its webhook output. This makes it a crucial component in a layered security strategy, providing real-time visibility into the runtime behavior of your applications.

What most people miss is how deeply Falco can understand the context of an event. It doesn’t just see a process running; it sees which container it’s in, what Kubernetes namespace and pod it belongs to, who the user is, and what system calls it’s making. This rich contextual data, derived from kernel events and enriched by Kubernetes metadata, is what allows for highly specific and actionable alerts, rather than noisy, generic warnings.

The next step after mastering runtime security with Falco is often exploring how to automatically respond to these detected threats, perhaps by terminating a suspicious pod or isolating a node.

Want structured learning?

Take the full Falco course →