Falco

Install on a host
This is for Debian with modern ebpf
Breakdown: How Falco Talks to the Kernel
libscap— The Kernel WhispererThink of
libscapas Falco’s ears to the kernel.It sits in userspace and reads syscall events (or eBPF events) pushed into a ring buffer.
It doesn’t care how the events got there — could be from:
Old-school kernel module
Modern eBPF magic
🧠 “System CAPture” = libscap
libscapCAP = "Capture"
It pulls events like:
open(),execve(),socket(),mkdir(), etc.And hands it over to Falco’s engine to evaluate against security rules.
Concepts
Event Sources
by default falco consumes events from the Linux Kernel via drivers
This can be extended with plugins
Rules are partitioned by event source, meaning each rule applies to a specific source and is triggered exclusively by events from that source.
NOTE:- Falco does not support correlating events from different sources.
Falco uses different instrumentations to analyse the system workload and pass security events to userspace.
We usually refer to these instrumentations as drivers, since a driver runs in kernel space.
The driver provides the syscall event source since the monitored events are strictly related to the syscall context.
Modern eBPF in Falco means:
You don’t need to compile a kernel module or deal with the “which kernel headers?” nightmare.
Falco uses CO-RE (Compile Once, Run Everywhere) to run on different kernels without recompilation.
It's way more portable and works even on funky, custom or bleeding-edge kernels.
The minimal set of capabilities required by Falco to run the modern eBPF probe is the following:
CAP_SYS_BPF
CAP_SYS_PERFMON
CAP_SYS_RESOURCE
CAP_SYS_PTRACE
Need to implement for mordern embf probe
the 2 main required features are:
BPF ring buffer support. (https://www.kernel.org/doc/html/next/bpf/ringbuf.html)
A kernel that exposes BTF. (https://docs.kernel.org/bpf/btf.html)
Using --disable-source & --enable-source
Disables specific event sources while keeping others active. This is useful if you want to prevent Falco from consuming events from certain sources.
List of ignored sys calls
🔁 How Falco Handles Dropped Events
Every second, Falco checks how many system call events the kernel has sent.
It looks at:
Total syscalls processed
How many failed because the shared buffer (between kernel and Falco) was full
These failures = dropped events (Falco missed something!)
What Falco Does If Events Are Dropped
You can configure how Falco reacts:
ignore
Do nothing (default)
log
Write a CRITICAL log saying the buffer was full
alert
Raise a Falco alert about the dropped event
exit
Stop Falco with an error code (non-zero)
example log
Falco can limit how many alerts/logs it sends in a short time—to avoid flooding your logs or inbox.
🔕 Disabled by default
📦 Can be turned on in the
falco.yamlconfig under theoutputssectionhttps://falco.org/docs/reference/daemon/config-options/
Generating sample events
To quickly check if Falco’s rules are firing correctly, use the built-in event-generator tool.
https://github.com/falcosecurity/event-generator
list all tools
Falco Rules
Falco rules are written in YAML and consist of three main building blocks:
Rules
The main logic
Define when to trigger an alert (e.g., someone runs chmod 777 on /etc/shadow). Includes a condition and a message.
Macros
Reusable logic snippets
Think of them like shortcuts for common conditions. You can use them inside rules or other macros.
Lists
Groups of items
A bunch of values (like suspicious binaries, paths, usernames) you want to reuse. Can be used in macros/rules, but not directly as filters.
Falco rules files can also include version checks to prevent breakage.
required_engine_version
Makes sure the rule set only runs with a compatible Falco engine. Prevents crashes due to unsupported features.
required_plugin_versions
Ensures rules that rely on specific plugins (like cloud, k8s, etc.) only run when the correct versions are present.
Basic Elements of Falco Rules
🧠 1. Rule
A YAML object defining when an alert should fire.
Key fields:
rule: Unique name.desc: What it does.condition: Boolean logic based on event fields.output: Message, with%fieldplaceholders.priority: Severity (e.g., EMERGENCY → DEBUG).
Optional advanced fields:
exceptions,enabled,tags,warn_evttypes,skip-if-unknown-filterWhy it matters: Defines exactly what behavior Falco considers suspicious and how to report it.
🔍 2. Condition
Boolean expression triggering rule when true.
Can reference any supported event fields (syscall or metadata).
Example:
💬 3. Output
A templated message, interpolating event data:
%proc.cmdline,%user.name, etc.Supports transformations like
%toupper(user.name)
⚠️ 4. Priority
Indicates severity of alerts; not evaluation order.
Common levels:
EMERGENCY,ALERT,CRITICAL,ERROR,WARNING,NOTICE,INFORMATIONAL,DEBUGGuidelines:
Writing state = ERROR
Reading sensitive files = WARNING
Unexpected behavior = NOTICE
Policy violations = INFO
♻️ 5. Macros
Named, reusable condition snippets.
Can call one macro from another (if already defined).
Example:
🧭 What does evt.dir = < mean?
evt.diris short for "event direction"It indicates which direction the syscall is going:
**<**= entering the syscall (i.e., the syscall was just called)**>**= exiting the syscall (i.e., the syscall just finished)**<>**= either direction
📋 6. Lists
Named collections of values used inside conditions or other lists.
👁️ Visibility
Ordering matters:
Lists reference only earlier lists.
Macros reference only earlier macros, but any lists.
Rules can reference any macros, even ones defined later
TL;DR
Rules = core detection + metadata
Conditions = event-matching logic
Outputs = alert templates
Priority = severity classification
Macros = reusable bits of logic
Lists = reusable sets of values
Default and Local Rules Files
By default, Falco loads rules in this order (from falco.yaml):
/etc/falco/falco_rules.yaml– the official default rules/etc/falco/falco_rules.local.yaml– for local overrides/etc/falco/rules.d/– any extra rule files you drop here
⚙️ 2. Customize via CLI
Running Falco manually? Use the -r flag:
Load multiple files or directories
If you use
-r, Falco ignores the defaultrules_fileslist
🧩 3. Managing with falcoctl
The falcoctl tool (CLI or Helm-based):
Can download specific rule versions (via OCI artifacts)
Puts them in
/etc/falcoby defaultEnsures your rules match your Falco engine version
📦 What Are OCI Artifacts?
OCI = Open Container Initiative Originally, OCI defined a standard for container images. Now, it also supports generic files and packages (not just containers)—called OCI artifacts.
🔧 In the context of Falco:
Falco uses OCI artifacts to package and distribute:
Default rules
Plugins
Rulesets
Configs All of this is pushed to and pulled from OCI-compatible registries (like Docker Hub, GitHub Container Registry, or your own Harbor).
Condition Syntax
🔍 What Is a Condition?
A condition is a Boolean expression that filters events—if it evaluates to true, the rule fires, producing an alert
Typically, it combines:
Event fields (like evt.type, proc.name, fd.name)
Comparison operators (=, !=, <, >, contains, in, glob, pmatch, etc.)
Logical operators (and, or, not)
Transformers (e.g., toupper(field), or % placeholders in outputs)
🛠️ Operators Explained
Logical operators
and, or, not: Combine or negate comparisons
Comparison operators
=,!=,<,>,<=,>=: Numerics or strict equalitycontains,icontains(case-insensitive),bcontains(byte-level)endswith,glob,pmatch(prefix matching)exists: checks presence of a fieldin,intersects: for sets or lists
🧠 Example Condition
Triggers on shell execs entering via
execve, specifically forcatorgrepYou can also use macros and lists to simplify and modularize your logic.
⚙️ Best Practices for Condition Writing
Start with
evt.typeearly in the condition to filter by event, improving performanceUse positive matches (
evt.type = execve, not!=) to avoid unnecessary overheadIsolate event types — don’t mix unrelated syscalls in a single rule for clarity and speed
TL;DR
✔️ Conditions are Boolean filters deciding when alerts fire.
✔️ Use logical, comparison, and set operators smartly.
✔️ Pre-filter with
evt.typeat the start.✔️ Prefer positive logic and keep conditions focused.
https://falco.org/docs/concepts/rules/conditions/
Overriding Rules
🔄 1. What Override Means
You can customize or tweak default Falco rules without touching them directly by either:
Splitting files — put your custom logic in a separate YAML loaded after the defaults.
Using an
overrideblock within that custom file to enlarge or replace parts of rules, macros, or lists.
⚙️ 2. How Overriding Works
In your custom rule file (e.g. falco_rules.local.yaml), you target an existing object using its name and specify changes via override:
append→ adds onto an existing elementreplace→ completely substitutes the element
You can’t mix append and replace on the same item.
What you can override:
List
items
items
Macro
condition
condition
Rule
condition, output, desc, tags, exceptions
condition, output, desc, priority, tags, exceptions, enabled, warn_evttypes, skip-if-unknown-filter falco.org
🔄 1. What Override Means
You can customize or tweak default Falco rules without touching them directly by either:
Splitting files — put your custom logic in a separate YAML loaded after the defaults.
Using an
overrideblock within that custom file to enlarge or replace parts of rules, macros, or lists.
⚙️ 2. How Overriding Works
In your custom rule file (e.g. falco_rules.local.yaml), you target an existing object using its name and specify changes via override:
append→ adds onto an existing elementreplace→ completely substitutes the element
You can’t mix append and replace on the same item.
What you can override:
List
items
items
Macro
condition
condition
Rule
condition, output, desc, tags, exceptions
condition, output, desc, priority, tags, exceptions, enabled, warn_evttypes, skip-if-unknown-filter falco.org
🛠️ 3. Real Examples
🧩 Append to a list
Default:
Your file:
Result: cp is added, so the list becomes [ls, cat, pwd, cp].
🧩 Replace a list
Result: Old list replaced entirely with [vi, vim, nano].
🧩 Append to a macro
Default:
Your file:
Result: Macro now matches both evt.type = open and openat.
🧩 Modify a rule
Result:
Condition gets more checks appended (e.g., and not user.name=root)
Output is completely replaced by yours.
❗ Rule Exceptions
Let you whitelist specific combos that should not trigger alerts.
This allows nginx to write under /etc/nginx without raising an alert
Best Practices:
Use 2+ fields (e.g.,
proc.name+fd.name)Avoid overly broad exceptions
You can override exceptions using
appendorreplace
🛑 Disabling or Enabling Rules via Config/CLI
Since Falco 0.38.0, you can selectively enable or disable rules/tags in your falco.yaml under the rules: section, or via CLI/Helm:
🔤 Acronym Glossary
system call
Syscalls stands for system calls, a way to request a service from the running kernel.
Reference
https://falco.org/docs/
https://docs.kernel.org/bpf/btf.html
https://www.kernel.org/doc/html/next/bpf/ringbuf.html
https://falco.org/docs/reference/daemon/config-options/
https://github.com/falcosecurity/event-generator
https://falco.org/blog/adaptive-syscalls-selection/
https://falco.org/docs/concepts/rules/conditions/
Last updated