Scanning images at build time tells you about known bad code. It says nothing about the compromised process spawning a shell in your payments pod at 2am. Runtime security watches actual behavior and catches the things static analysis never will.
Detect with Falco
Falco taps kernel events via eBPF and fires on suspicious behavior. A rule is a hypothesis about what should never happen:
- rule: Shell in a container
desc: A shell was spawned inside a running container
condition: >
spawned_process and container
and proc.name in (bash, sh, zsh)
and not container.image.repository in (allowed_debug_images)
output: >
Shell spawned (user=%user.name container=%container.name
image=%container.image.repository cmd=%proc.cmdline)
priority: WARNING
tags: [container, shell, mitre_execution]Enforce with Tetragon
Detection tells you after the fact. Tetragon can block the action in-kernel. Here it kills any process that tries to read a sensitive file:
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata: { name: block-secret-reads }
spec:
kprobes:
- call: security_file_open
selectors:
- matchArgs:
- index: 0
operator: Prefix
values: ["/etc/shadow", "/var/run/secrets"]
matchActions:
- action: Sigkill # stop it before the read completesRespond, do not just alert
Route high-severity events to the on-call channel with full context
Auto-isolate a pod (NetworkPolicy) on confirmed compromise
Snapshot the node for forensics before you kill anything
Feed detections back into tighter policy over time
Prevention fails eventually. Detection plus fast response is what turns a breach into an incident instead of a headline.
Pair build-time scanning with runtime detection and in-kernel enforcement. Defense in depth means assuming something gets in, and making sure it cannot do anything useful once it does.



