Falco: Kubernetes Runtime Security and Threat Detection (2026)

Falco is a cloud-native runtime security tool that detects anomalous behaviour in containers and Kubernetes nodes by monitoring system calls. While admission controllers like OPA Gatekeeper enforce policy at deploy time, Falco watches what is actually happening at runtime — detecting threats like privilege escalation, unexpected shell spawns, file access in sensitive paths, and network connections from containers that shouldn't be making them.

How Falco Works

Falco uses a kernel driver (either a kernel module or eBPF program) to intercept system calls made by every process on the node. These syscalls are streamed to the Falco engine, which evaluates them against a rule set. When a rule matches, Falco emits an alert with severity, metadata about the process, container, and Kubernetes pod, and the triggered rule's output message.

This approach gives Falco visibility that admission controllers cannot provide:

  • A container that was deployed correctly can still be compromised at runtime.
  • An attacker who gains code execution inside a container will trigger system calls that Falco can detect — even if they use a legitimate image.
  • Falco detects behaviour, not configuration — it catches what attackers do, not just what they are allowed to do.
Falco vs OPA Gatekeeper: These tools are complementary, not competing. Gatekeeper prevents bad workloads from being admitted. Falco detects bad behaviour in workloads that are already running. Use both.

Installing Falco on Kubernetes

Falco runs as a DaemonSet so it monitors every node:

# Add the Falco Helm repository
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update

# Install Falco with eBPF driver (recommended for modern kernels)
helm install falco falcosecurity/falco \
  --namespace falco \
  --create-namespace \
  --set driver.kind=ebpf \
  --set falcosidekick.enabled=true \
  --set falcosidekick.webui.enabled=true

# Verify DaemonSet is running
kubectl get pods -n falco
# NAME              READY   STATUS    NODE
# falco-5xk9v       2/2     Running   node-1
# falco-7m4pn       2/2     Running   node-2
# falco-9q2rs       2/2     Running   node-3

Check that Falco is detecting events:

kubectl logs -n falco daemonset/falco -c falco | head -20

Understanding Falco Rules

A Falco rule has four key fields:

- rule: Terminal shell in container
  desc: A shell was spawned inside a container
  condition: >
    spawned_process
    and container
    and shell_procs
    and proc.tty != 0
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
     image=%container.image.repository
     shell=%proc.name cmdline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, mitre_execution]
  • condition — a boolean expression over syscall fields (proc.*, container.*, fd.*, evt.*). Falco evaluates this for every matching syscall.
  • output — a message template with field substitutions. Printed when the rule triggers.
  • priority — severity level: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY.
  • tags — used for filtering and MITRE ATT&CK mapping.

Built-in Rules and Macros

Falco ships with a comprehensive default rule set covering the most common attack patterns. Key built-in rules include:

  • Terminal shell in container — detects interactive shells spawned inside running containers (common post-exploitation step).
  • Write below binary dir — detects writes to /bin, /usr/bin, /sbin inside a container.
  • Read sensitive file untrusted — detects reads of /etc/shadow, /etc/sudoers, SSH keys by non-trusted processes.
  • Outbound network connection from container — detects unexpected egress from containers that shouldn't make outbound connections.
  • Container run as root user — alerts when a container process runs as UID 0.
  • Modify binary dirs — detects modifications to system binary directories.
  • Launch Disallowed Container — when combined with image policies, detects containers launched from unlisted images.

Falco also ships macros (reusable condition fragments) and lists (reusable value sets) that you can override in custom rule files:

# Example macro override — add your container names to trusted shells list
- list: trusted_shell_containers
  items: [debug-shell, ops-toolbox]
  override:
    items: append

Writing Custom Rules

Write custom rules in a separate YAML file and mount them alongside Falco's default rules:

# custom-rules.yaml

# Detect access to application secrets directory
- rule: Access to secrets directory
  desc: A process read from /app/secrets outside of the app container
  condition: >
    open_read
    and fd.name startswith /app/secrets
    and not proc.name in (app-server, config-loader)
    and container
  output: >
    Unauthorized access to secrets
    (user=%user.name proc=%proc.name file=%fd.name
     container=%container.name pod=%k8s.pod.name)
  priority: ERROR
  tags: [secrets, data-exfiltration]

# Detect cryptocurrency mining (stratum protocol)
- rule: Cryptocurrency mining detected
  desc: Outbound connection to common mining pool ports
  condition: >
    outbound
    and fd.sport in (3333, 4444, 8333, 9999, 14444)
    and container
  output: >
    Possible cryptocurrency mining
    (proc=%proc.name container=%container.name
     dest=%fd.rip:%fd.rport)
  priority: CRITICAL
  tags: [cryptomining, network]

Mount custom rules via Helm values:

helm upgrade falco falcosecurity/falco \
  --namespace falco \
  --set-file customRules.custom-rules\.yaml=custom-rules.yaml

Falcosidekick: Routing Alerts

Falcosidekick is a companion service that receives Falco alerts and forwards them to over 50 output destinations — Slack, PagerDuty, Elasticsearch, Loki, Datadog, AWS Lambda, and more:

helm install falco falcosecurity/falco \
  --namespace falco \
  --set falcosidekick.enabled=true \
  --set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/..." \
  --set falcosidekick.config.slack.minimumpriority="warning" \
  --set falcosidekick.config.pagerduty.routingkey="your-pagerduty-key" \
  --set falcosidekick.config.pagerduty.minimumpriority="error"

A Slack alert from Falco looks like:

{
  "rule": "Terminal shell in container",
  "priority": "WARNING",
  "time": "2026-06-11T10:23:45Z",
  "output": "Shell spawned in container (user=root container=payment-api image=payment:latest shell=bash)",
  "tags": ["container", "shell"],
  "kubernetes": {
    "pod": "payment-api-7d9f4c8b5-xz4qp",
    "namespace": "production",
    "node": "node-1"
  }
}

Tuning and Noise Reduction

Out of the box, Falco can generate a lot of noise from legitimate workloads. Tuning is essential before using Falco in production:

# Override a noisy rule to add exceptions
- rule: Write below etc
  desc: An attempt to write to /etc
  condition: >
    write_etc_common
    and not proc.name in (chef-client, puppet, ansible-playbook, my-config-tool)
  override:
    condition: append

Use priority filtering in Falcosidekick to only forward high-severity alerts to PagerDuty, while logging everything to Elasticsearch:

falcosidekick:
  config:
    pagerduty:
      minimumpriority: "critical"
    elasticsearch:
      hostport: "http://elasticsearch:9200"
      minimumpriority: "notice"
Noise budget: Track your false-positive rate per rule. Suppress or tune any rule firing more than a few times per hour from legitimate workloads — alert fatigue will cause real threats to be ignored.

eBPF Driver

Falco supports three driver modes:

  • Kernel module — classic approach, requires kernel headers. Blocks kernel upgrades until the module is recompiled. Not recommended for managed Kubernetes (EKS, GKE).
  • eBPF probe — loads a BPF program into the kernel. No kernel module. Works on most Linux kernels ≥ 4.14. Recommended for most clusters.
  • Modern eBPF — uses CO-RE (Compile Once – Run Everywhere) BTF-based eBPF. No build step. Requires kernel ≥ 5.8. Best option for modern distributions.
# Install with modern eBPF (best option for Kubernetes 1.28+)
helm install falco falcosecurity/falco \
  --namespace falco \
  --set driver.kind=modern_ebpf

Production Best Practices

  • Run as DaemonSet with resource limits — Falco runs on every node. Set memory limits to prevent it from starving other workloads. Typical usage is 200-500MB per node.
  • Enable the audit log plugin — Falco can also consume Kubernetes audit logs to detect API-level threats like unauthorized RBAC changes or Secret reads.
  • Use the Falco Helm chart for upgrades — it handles kernel module/eBPF probe rebuilds and rule set updates cleanly.
  • Integrate with SIEM — forward all Falco events to your SIEM (Splunk, Elastic SIEM, Chronicle) for historical threat hunting.
  • Test your rules — use the event-generator tool from Falco's test suite to trigger known-bad behaviours and verify your alerting pipeline works end-to-end.
# Test Falco alerting with event-generator
kubectl run event-generator \
  --image=falcosecurity/event-generator \
  --restart=Never -- run syscall

FAQ

Does Falco block threats?
No. Falco is a detection tool, not a prevention tool. It alerts on suspicious behaviour but does not terminate processes or block syscalls. Use Falco alerts to trigger automated responses (via Falcosidekick → Lambda/webhook) that can take remediation action.
Does Falco impact application performance?
Syscall interception adds overhead. In benchmarks, Falco with eBPF adds 1-3% CPU overhead on typical workloads. Applications making very high syscall rates (database engines, high-throughput network services) may see higher overhead.
Can Falco monitor the Kubernetes API server?
Yes, via the Kubernetes audit log plugin. Configure the API server to send audit events to Falco, and Falco can detect control-plane threats like unauthorized Secret reads, RBAC privilege escalations, and suspicious API calls.
← Kubernetes Hub
Get Weekly Tech Insights

Join 5,000+ engineers getting the best Kubernetes, Java, Cloud and AI articles every week.