Falco
Falco is the CNCF runtime-security project: a detection engine that watches a running system and raises alerts when behavior matches a security rule (Falco docs). It is the complement to admission control. Where OPA Gatekeeper, Kyverno, and Pod Security Admission gate what may be created, Falco observes what processes actually do once running — a shell spawned inside a container, a write to
/etc/shadow, an unexpected outbound connection, a package manager invoked in production. Falco consumes a high-volume kernel event stream — Linux syscalls, captured by a modern eBPF probe — enriches each event with container and Kubernetes metadata, and evaluates it against Falco Rules (YAML: a condition, an output template, a priority). Falco originated at Sysdig, was donated to the CNCF in 2018, and reached CNCF Graduated maturity in February 2024 (Falco graduation blog).
Mental Model
The single most important framing — and the dispatch states it correctly — is admission control gates creation; Falco watches runtime. A malicious or compromised workload can pass every admission policy (its manifest is perfectly compliant) and then misbehave: an attacker exploits a vulnerable web server, gets a shell, and starts probing. Admission control is blind to this; it already approved the Pod. Falco is the defense-in-depth layer that sees the behavior, not the declaration. This is why the Kubernetes MOC decision framework says “choose admission policies over runtime detection, then add runtime detection as defense in depth” — they are not substitutes.
Mechanically, Falco is a pipeline: an event source produces a stream of events; the rule engine filters that stream against compiled rules; matched events become alerts routed to outputs.
flowchart LR subgraph kernel["Linux kernel"] SC["syscalls<br/>(open, execve, connect, ...)"] end SC -->|"eBPF probe<br/>(or kmod, legacy)"| DRV["Falco driver<br/>captures + filters in kernel"] DRV --> ENR["userspace:<br/>enrich with container +<br/>K8s metadata"] KAUD["K8s audit events<br/>(plugin source)"] --> ENR ENR --> ENG["rule engine<br/>(evaluate Falco Rules)"] ENG -->|"match"| ALERT["alert<br/>(priority + output)"] ALERT --> OUT["outputs:<br/>stdout / file / gRPC / syslog"] OUT --> SK["Falcosidekick<br/>fan-out to Slack, SIEM,<br/>PagerDuty, S3, ..."]
The Falco pipeline. Insight to extract: the driver runs in the kernel (eBPF or kernel module) and does early filtering there — critical, because the raw syscall stream is enormous and copying all of it to userspace would be prohibitively expensive. Enrichment and rule evaluation happen in userspace. Kubernetes audit events enter as a separate plugin source, not through the kernel.
Mechanical Walk-through
Event sources and the driver
Falco’s primary source is the system-call event stream. Capturing it requires a kernel-side driver. There are three driver options, and the dispatch’s “eBPF modern, kernel-module legacy” framing is the accurate guidance:
- Modern eBPF probe (
modern_ebpf) — the current default and recommended driver. It is a CO-RE (Compile Once, Run Everywhere) eBPF program embedded in the Falco binary; it needs no per-kernel compilation and no out-of-tree module, just a recent-enough kernel (roughly 5.8+). - Legacy eBPF probe — an older eBPF driver that required a separately built
.oobject; superseded by modern eBPF. - Kernel module (
kmod) — the original driver: an out-of-tree kernel module. It works on older kernels but must be compiled/matched per kernel version and carries the operational risk of any kernel module. Treated as legacy where eBPF is available.
There is also a gVisor integration for sandboxed workloads, where syscalls are observed at the gVisor sentry rather than the host kernel.
The driver does in-kernel filtering: the raw syscall firehose is far too large to ship wholesale to userspace, so the driver drops events Falco does not care about before they cross the kernel/userspace boundary. (Persistent Dropped Syscall Events warnings in Falco’s logs mean the host is producing events faster than Falco can consume — a tuning signal.)
Plugins: non-syscall sources
Beyond syscalls, Falco supports plugins that feed other event streams into the same rule engine. The most relevant for Kubernetes is the Kubernetes Audit Logs plugin — Falco consumes the audit event stream from the apiserver and applies rules to it (e.g. “alert when a ConfigMap with sensitive data is created”, “alert on a privileged Pod”). Other plugins cover AWS CloudTrail, Okta, GitHub, and more — making Falco a general behavioral-detection engine, not only a syscall monitor.
Metadata enrichment
A raw execve syscall says only “PID 4711 exec’d /bin/sh.” Falco’s userspace component enriches it with the container ID, image name, container name, and — via the cluster API — the Pod name, namespace, labels. This is what lets a rule’s output say “shell spawned in container web of pod frontend-7d9 in namespace prod” instead of a bare PID. The enrichment is what makes Falco alerts actionable in a Kubernetes context.
Falco Rules
A rule is YAML with, at minimum, a condition, an output, and a priority. The condition is a boolean filter expression over event fields (evt.type, proc.name, fd.name, container.image.repository, k8s.ns.name, …). The output is a templated string interpolating those fields. The priority is a syslog-style severity (EMERGENCY…DEBUG; commonly WARNING, ERROR, CRITICAL).
Rules are composed from two reuse primitives: macros (named, reusable condition fragments — e.g. spawned_process = evt.type in (execve, execveat) and evt.dir = <) and lists (named collections of values — e.g. shell_binaries = [bash, sh, zsh, ...]). Falco ships a default ruleset (falco_rules.yaml); production users layer their own rules and exceptions on top via override mechanisms rather than editing the defaults.
Detections Falco is built for
The canonical detections, all of which are runtime behaviors invisible to admission control:
- A shell run in a container —
Terminal shell in containerrule; a strong indicator of an interactive intrusion. - A write to a sensitive path — modification of
/etc,/bin, or other read-only-by-policy locations. - An unexpected outbound connection — a workload connecting to an unknown IP/port (C2 beaconing, exfiltration).
- A package manager run in a running container —
apt/yum/apkexecuting at runtime, which should never happen in an immutable container. - Privilege escalation / unexpected root —
setuidcalls, a container behaving as root when it should not. - Sensitive file reads — a process reading
/etc/shadow.
Outputs and Falcosidekick
Falco’s built-in outputs are deliberately minimal: stdout, a file, syslog, and a gRPC API. To route alerts to real destinations, the project ships Falcosidekick — a companion daemon that consumes Falco’s output and fans it out to 50+ targets: Slack, PagerDuty, a SIEM (Splunk, Elasticsearch), object storage (S3), webhooks, FaaS triggers, and more. The pattern is Falco detects, Falcosidekick distributes. Falcosidekick also has a UI for browsing alerts.
Configuration / API Surface
Falco deploys as a DaemonSet (one pod per node — it must observe every node’s kernel) and is configured with falco.yaml plus rule files. A custom rule, with a list and a macro:
# --- a list: reusable set of values ---
- list: sensitive_paths
items: [/etc/shadow, /etc/sudoers, /root/.ssh]
# --- a macro: reusable condition fragment ---
- macro: open_for_read
condition: (evt.type in (open, openat, openat2) and evt.is_open_read=true)
# --- the rule itself ---
- rule: Read sensitive file in container # unique rule name
desc: A process inside a container read a credential file
condition: > # the boolean filter
open_for_read # reuse the macro
and container.id != host # only inside containers
and fd.name in (sensitive_paths) # reuse the list
output: > # templated alert string
Sensitive file read (file=%fd.name proc=%proc.name
container=%container.name image=%container.image.repository
pod=%k8s.pod.name ns=%k8s.ns.name)
priority: WARNING # syslog-style severity
tags: [filesystem, mitre_credential_access] # for grouping / routingLine-by-line: the list sensitive_paths and the macro open_for_read are reusable building blocks referenced by name in the rule. The rule’s condition ANDs the macro, a container scope guard (container.id != host), and a file-path check against the list. The output interpolates event fields — note %k8s.pod.name and %k8s.ns.name, which only resolve because of metadata enrichment. priority drives severity-based routing; tags (here including a MITRE ATT&CK technique) help downstream tools group alerts.
Failure Modes
- Dropped syscall events. If the host generates events faster than Falco consumes them, the driver drops events and Falco logs
Falco internal: syscall event drop. Dropped events are missed detections — a security blind spot, not a cosmetic warning. Mitigations: tune the driver buffer, reduce rule complexity, or accept the drop policy. This is the most common Falco operational problem. - Kernel/driver mismatch. With the
kmoddriver, a node kernel without a matching prebuilt module forces a slow on-node compile or fails outright. The modern eBPF (CO-RE) driver largely eliminates this — a strong reason to prefer it. - Noisy default rules / alert fatigue. Out-of-the-box rules fire on benign activity (CI base-image builds run package managers, admins exec into pods deliberately). Untuned Falco buries real alerts under noise. Tuning via exceptions is mandatory, not optional.
- No prevention. Falco detects and alerts; by itself it does not block. Stopping the attack requires a response loop —
falco-talonor a Falcosidekick→FaaS reaction that kills the pod. Treating Falco as a preventive control is a category error. - Per-node resource cost. As a DaemonSet processing the syscall stream, Falco consumes CPU and memory on every node; on syscall-heavy nodes this is non-trivial.
Alternatives and When to Choose Them
- Admission control (OPA Gatekeeper / Kyverno / Pod Security Admission) — not an alternative but a complement. Admission stops bad configuration before it runs; Falco catches bad behavior after. The mature posture runs both. Cheaper to catch a problem at admission, so admission is the first line; Falco is defense in depth.
- Tetragon (Cilium) — an eBPF-based runtime-security and observability tool from the Cilium project. Tetragon emphasizes enforcement (it can kill or block from kernel context) more than Falco’s detection focus, and is tied to the Cilium ecosystem. Choose Tetragon if in-kernel enforcement and Cilium integration matter; choose Falco for the broad rule library, plugin sources (cloud audit logs), and vendor-neutral CNCF-graduated maturity.
- Commercial CNAPP/EDR agents (Sysdig Secure, Aqua, Falco’s own commercial descendants) — build on or beside Falco with managed rules, response automation, and compliance reporting. Choose these when you want a supported product rather than self-operated open source; Falco is the open core many of them share.
auditd— the traditional Linux audit daemon also captures syscalls, but lacks container/Kubernetes enrichment, a portable rule language, and the cloud-native output ecosystem. Falco is purpose-built for the container world.
Production Notes
- CNCF Graduated since February 2024 — created by Sysdig, donated 2018, Incubating 2020, Graduated 2024. Graduation signals production maturity and broad adoption.
- Recent release line is v0.43.x (January 2026); Falco is one of the largest open-source eBPF codebases in existence.
- Standard deployment is the Helm chart or the Falco Operator, as a DaemonSet, with
modern_ebpfas the driver on modern kernels. - The detection rules are kept in a separate, versioned Falco Rules repository (
falcosecurity/rules) so the engine and the rule content evolve independently — analogous to the gatekeeper-library / kyverno-policies split. - Tuning is the real work: budget time for exception-writing against your actual workloads before Falco’s signal-to-noise ratio is good enough to act on.
See Also
- OPA Gatekeeper — admission-time policy; the create-time complement to Falco’s runtime detection
- Kyverno — admission-time policy engine; the create-time complement
- Pod Security Admission — built-in admission hardening; create-time complement
- Kubernetes Audit Logging — the apiserver audit stream Falco can consume as a plugin source
- Image Signing with Sigstore — supply-chain provenance; another defense-in-depth layer
- Cilium — the eBPF CNI; its Tetragon component is a runtime-security alternative
- SecurityContext — the per-container privilege controls Falco watches for violations of
- Kubernetes MOC — parent map, §12 Security