KCSA — Falco — Runtime Threat Detection
Falco — Runtime Threat Detection
Traditional security tools focus on preventing bad things from being deployed. But what happens when a threat bypasses prevention — a compromised container, a zero-day exploit, or an insider threat? That is where runtime security comes in, and Falco is the leading open-source tool for runtime threat detection in Kubernetes.
What Is Falco?
Falco is a CNCF Graduated project that detects unexpected application behavior and alerts on threats at runtime. Originally created by Sysdig in 2016, Falco monitors system calls (syscalls) made by containers and processes, compares them against a set of rules, and generates alerts when suspicious activity is detected.
Falco does NOT prevent or block threats — it detects and alerts. Think of Falco as a security camera, not a lock on the door.
Key characteristics:
- Runtime detection — monitors activity as it happens, not at deploy time
- Syscall-level visibility — sees what processes actually do inside containers
- Rule-based engine — flexible YAML rules define what constitutes a threat
- CNCF Graduated — production-ready, widely adopted in the ecosystem
- Lightweight — minimal performance overhead when using eBPF
Falco Architecture
Falco has a three-layer architecture:
┌─────────────────────────────────────────────────┐
│ Alerting / Output │
│ (stdout, file, syslog, HTTP, gRPC, Slack) │
├─────────────────────────────────────────────────┤
│ Userspace Rules Engine │
│ (loads rules → matches against events) │
├─────────────────────────────────────────────────┤
│ Kernel Data Source (Driver) │
│ (kernel module OR eBPF probe OR plugin) │
├─────────────────────────────────────────────────┤
│ Linux Kernel │
│ (syscalls from containers) │
└─────────────────────────────────────────────────┘
The Three Layers
| Layer | Component | Purpose |
|---|---|---|
| Data Source | Kernel module / eBPF probe | Captures raw syscall events from the kernel |
| Rules Engine | Userspace Falco process | Evaluates events against loaded rules |
| Output | Alert channels | Sends notifications when a rule matches |
Driver Options
Falco supports multiple drivers to capture kernel events:
| Driver | Description | Pros | Cons |
|---|---|---|---|
| Kernel Module | Traditional Linux kernel module | Full feature support | Requires module loading, kernel version dependency |
| eBPF Probe | Modern eBPF-based data collection | No kernel module needed, safer | Requires kernel ≥ 4.14 with eBPF support |
| Modern eBPF | CO-RE (Compile Once — Run Everywhere) eBPF | Portable across kernel versions | Requires kernel ≥ 5.8 |
| Plugin | Reads from external sources (CloudTrail, K8s audit log) | Extends beyond syscalls | Source-specific |
For the KCSA exam, know that eBPF is the recommended modern approach for capturing syscall data — it is safer than kernel modules and does not require compiling against specific kernel headers.
How Falco Works
The detection flow is straightforward:
- A container or process makes a syscall (e.g.,
open(),execve(),connect()) - Falco’s driver captures the event from the kernel
- The rules engine evaluates the event against all loaded rules
- If a rule matches, Falco generates an alert through configured output channels
- If no rule matches, the event is silently discarded
Container → syscall → kernel → Falco driver → rules engine → alert (if matched)
Falco processes millions of syscalls per second — the eBPF driver ensures minimal performance impact by filtering at the kernel level before events reach userspace.
Falco Rules Structure
Falco rules are written in YAML and consist of three main constructs: rules, macros, and lists.
Rule Anatomy
- rule: Terminal shell in container
desc: >
A shell was used as the entrypoint/exec point into a container
with an attached terminal.
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
and container_entrypoint
output: >
A shell was spawned in a container with an attached terminal
(user=%user.name user_loginuid=%user.loginuid %container.info
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline
terminal=%proc.tty container_id=%container.id image=%container.image.repository)
priority: NOTICE
tags: [container, shell, mitre_execution]
Rule Components
| Component | Purpose | Example |
|---|---|---|
rule |
Human-readable name | Terminal shell in container |
desc |
Description of what the rule detects | A shell was spawned … |
condition |
Sysdig filter expression that must match | spawned_process and container and shell_procs |
output |
Alert message template with context fields | user=%user.name container_id=%container.id |
priority |
Severity level of the alert | NOTICE, WARNING, ERROR, etc. |
tags |
Labels for categorization and filtering | [container, shell, mitre_execution] |
Macros and Lists
Macros are reusable condition snippets:
- macro: container
condition: container.id != host
- macro: shell_procs
condition: proc.name in (shell_binaries)
Lists are named collections of values:
- list: shell_binaries
items: [bash, csh, ksh, sh, tcsh, zsh, dash]
Macros and lists keep rules DRY (Don’t Repeat Yourself) and make rules easier to read and maintain.
Default Falco Rules — Common Examples
Falco ships with a comprehensive set of default rules. Here are the most exam-relevant ones:
Terminal Shell in Container
What it detects: An interactive shell session started inside a running container — a common indicator of compromise or unauthorized access.
- rule: Terminal shell in container
condition: spawned_process and container and shell_procs and proc.tty != 0
priority: NOTICE
Write Below /etc
What it detects: Any process writing to the /etc directory inside a container, which could indicate configuration tampering.
- rule: Write below etc
condition: write_etc_common and open_write and container and not write_etc_allowed
priority: ERROR
Read Sensitive File /etc/shadow
What it detects: A process reading the shadow password file, which could indicate credential harvesting.
- rule: Read sensitive file untrusted
condition: sensitive_files and open_read and container and not trusted_reading_sensitive
priority: WARNING
Launch Privileged Container
What it detects: A container running in privileged mode, which grants full access to the host kernel.
- rule: Launch Privileged Container
condition: container_started and container and container.privileged=true
priority: INFO
Contact Kubernetes API Server from Container
What it detects: A container making network connections to the Kubernetes API server — potentially an attacker trying to interact with the cluster.
- rule: Contact K8S API Server From Container
condition: outbound and container and k8s_api_server
priority: NOTICE
Each default rule maps to a known attack technique in the MITRE ATT&CK framework for containers.
Falco Rule Priorities
Falco uses eight priority levels to classify alert severity:
| Priority | Level | Description | Example |
|---|---|---|---|
| EMERGENCY | 0 | System is unusable | Kernel compromise detected |
| ALERT | 1 | Action must be taken immediately | Container escape detected |
| CRITICAL | 2 | Critical conditions | Privileged container launched on production node |
| ERROR | 3 | Error conditions | Write to sensitive system directory |
| WARNING | 4 | Warning conditions | Read of sensitive file like /etc/shadow |
| NOTICE | 5 | Normal but significant | Interactive shell opened in container |
| INFORMATIONAL | 6 | Informational messages | New container started |
| DEBUG | 7 | Debug-level messages | Detailed syscall trace |
For the KCSA exam, remember the relative order — EMERGENCY is the most severe, DEBUG is the least severe.
Falco Output Channels
When a rule matches, Falco can send alerts through multiple output channels simultaneously:
| Channel | Use Case |
|---|---|
| stdout | Container logs, simplest option, works with kubectl logs |
| File | Write alerts to a log file on the host |
| Syslog | Forward to system logging infrastructure |
| HTTP Webhook | POST alerts to an external endpoint |
| gRPC | Stream alerts to a gRPC client |
| Program | Pipe alerts to an external program |
Configuration Example
# falco.yaml output configuration
stdout_output:
enabled: true
file_output:
enabled: true
filename: /var/log/falco/events.log
http_output:
enabled: true
url: http://falcosidekick:2801
Falco Deployment Options
Falco can be deployed in several ways on Kubernetes:
| Deployment | Description | When to Use |
|---|---|---|
| DaemonSet | Runs on every node as a privileged pod | Most common — production Kubernetes clusters |
| Host-based | Installed directly on the node OS | When you cannot run privileged containers |
| Sidecar | Runs alongside a specific application pod | Narrow monitoring of critical workloads |
| Helm Chart | Deploy via helm install falcosecurity/falco |
Standard Kubernetes installation method |
The DaemonSet model ensures every node in the cluster is monitored. Because Falco needs access to kernel syscalls, the pod runs with elevated privileges.
# Install Falco via Helm (conceptual — KCSA is not hands-on)
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true
Falcosidekick — Alert Forwarding
Falcosidekick is a companion project that takes Falco alerts and forwards them to 50+ external destinations:
| Destination | Purpose |
|---|---|
| Slack | Team notifications |
| PagerDuty | On-call incident response |
| Microsoft Teams | Enterprise team chat |
| Elasticsearch | Searchable alert storage |
| AWS CloudWatch | Cloud-native logging |
| Prometheus | Metrics for alerting dashboards |
| Kubernetes (response engine) | Automated remediation (e.g., kill pod) |
Falcosidekick decouples Falco’s detection from the response — Falco focuses on what it does best (detecting threats), while Falcosidekick handles routing alerts to the right teams and systems.
Falco → Falcosidekick → [ Slack, PagerDuty, Elasticsearch, ... ]
Falcosidekick can also trigger automated responses — for example, deleting a compromised pod when a critical alert fires. This is called a response engine.
Falco vs Kubernetes Audit Logs
Both Falco and Kubernetes audit logs detect security-relevant events, but they operate at different layers:
| Aspect | Falco | Kubernetes Audit Logs |
|---|---|---|
| What it monitors | Syscalls inside containers and on the host | API server requests (create, delete, patch, etc.) |
| Visibility | What processes actually do at runtime | What users/systems request from the API server |
| Detection scope | Container escape, shell access, file tampering, network connections | RBAC violations, secret access, resource creation |
| Data source | Kernel (eBPF/kernel module) | kube-apiserver |
| Deployment | DaemonSet on every node | Built into the API server |
| Rule format | Falco YAML rules | Audit policy YAML (level: Metadata/Request/RequestResponse) |
They are complementary, not competing. A comprehensive security posture uses both:
- Audit logs catch “who asked to do what” at the API level
- Falco catches “what actually happened” at the syscall level
A compromised container making raw network connections bypassing the API server would be invisible to audit logs but visible to Falco.
Falco and the MITRE ATT&CK Framework
Falco’s default rules are tagged with MITRE ATT&CK technique IDs, mapping each detection to a known adversary technique:
| MITRE Technique | Falco Rule Example |
|---|---|
| Execution (T1059) | Terminal shell in container |
| Persistence (T1546) | Write below /etc |
| Credential Access (T1552) | Read sensitive file /etc/shadow |
| Privilege Escalation (T1611) | Launch privileged container |
| Discovery (T1613) | Contact K8S API Server from container |
This mapping helps security teams correlate Falco alerts with the broader threat landscape and prioritize response accordingly.
Key Takeaways for the Exam
- Falco is a CNCF Graduated runtime security tool — it detects threats at runtime, it does NOT prevent or block them
- Falco uses eBPF (or kernel module) to capture syscall data from the Linux kernel
- Rules are YAML-based with condition, output, and priority fields — macros and lists keep rules DRY
- Eight priority levels from EMERGENCY (most severe) to DEBUG (least severe)
- DaemonSet is the standard deployment — runs on every node with elevated privileges
- Falcosidekick forwards alerts to 50+ destinations (Slack, PagerDuty, Elasticsearch)
- Falco + audit logs are complementary — Falco sees syscalls, audit logs see API requests
- Default rules map to MITRE ATT&CK techniques for threat classification
- Falco is detection, not prevention — it tells you something bad happened, OPA/Kyverno prevent bad deployments