Everything you do before deployment — scanning images, hardening Dockerfiles, verifying signatures — reduces the odds of a breach. None of it tells you when one is actually happening. A container that passed every pre-deploy gate can still be compromised through a zero-day in the application, a leaked credential, or a dependency that turned malicious after you shipped it. Runtime security monitoring is the layer that watches live containers and flags behavior that should never occur: a shell spawning inside a service that has no business running one, a process reading /etc/shadow, an outbound connection to an unknown host, a write to a binary directory on a read-only filesystem. The container-escape CVEs that keep appearing — the runc breakout family, the containerd-shim socket exposure in CVE-2020-15257, cgroups escapes like CVE-2022-0492 — are exactly the events runtime monitoring exists to catch, because by definition they defeat the pre-deploy assumption that the container stays in its box.
Why runtime monitoring is a distinct discipline
Pre-deploy scanning reasons about artifacts: is this package vulnerable, is this image signed, does this manifest run as root? Runtime monitoring reasons about behavior: is this running process doing something anomalous right now? The two are complementary and neither replaces the other. Scanning cannot detect a credential compromise, and monitoring cannot un-ship a vulnerable image. What monitoring adds is a detection-and-response capability for the window between "deployed" and "exploited," which is precisely where scanning has nothing to say.
The engine: eBPF and syscall visibility
Modern runtime security is built on eBPF, which lets tooling observe kernel-level events — system calls, file access, network connections, process execution — with low overhead and without kernel modules. Falco, a CNCF project, is the reference open-source implementation: it consumes this syscall stream and evaluates it against a rule set, emitting alerts when behavior matches a suspicious pattern. Other tools in the space (Tetragon, and commercial platforms) build on the same eBPF foundation. The key idea is that you are watching the actual behavior of the workload at the kernel boundary, where an attacker's actions — spawning a shell, opening a socket, escalating privileges — must ultimately surface, no matter how they got in.
The detections that earn their keep
A handful of behavioral rules catch a disproportionate share of real container attacks. A Falco rule to flag a shell spawned inside a container looks like this:
- rule: Terminal shell in container
desc: A shell was spawned in a container, which most services never do
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
and not user_expected_terminal_shell_in_container_conditions
output: >
Shell spawned in container (user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
priority: WARNING
tags: [container, shell, mitre_execution]
The categories worth alerting on:
- Unexpected process execution — a shell,
curl,wget, or a package manager running inside a service image that should only ever run its own binary. - Filesystem drift — writes to
/usr/bin,/etc, or other locations that should be immutable, indicating a container has been modified from its image. - Sensitive file access — reads of
/etc/shadow, cloud credential files, or service account tokens. - Privilege escalation and escape indicators — attempts to mount host paths, write to
release_agent, or access the container runtime socket. - Anomalous network activity — outbound connections to unexpected destinations, or a workload suddenly listening on a new port.
From alert to response
A firehose of alerts that nobody triages is worse than no monitoring, because it manufactures the illusion of coverage. Make runtime detection actionable:
- Baseline first. Most services have a narrow, stable set of normal behaviors. Tune rules to your workloads so a legitimate migration job does not page someone at 2 a.m.
- Route by severity. Escape indicators and sensitive-file reads warrant an immediate page; drift on a dev namespace can go to a dashboard.
- Automate containment for high-confidence events. Kill or quarantine a pod, revoke its service account token, and snapshot it for forensics — automatically — when a rule fires that is never a false positive.
- Feed detections back into prevention. A shell spawning in production is also a signal that the image should have been distroless and the pod should have had a read-only root filesystem.
Prevent-and-detect checklist
| Layer | Prevent (pre-deploy) | Detect (runtime) |
|---|---|---|
| Process | Distroless image, no shell | Alert on shell / unexpected exec |
| Filesystem | readOnlyRootFilesystem: true | Alert on writes to system paths |
| Privilege | Drop capabilities, non-root | Alert on escalation attempts |
| Network | Deny-by-default NetworkPolicy | Alert on anomalous egress |
| Identity | Minimal service account | Alert on token/credential access |
How Safeguard helps
Runtime monitoring is most powerful when the alerts are connected to the artifacts that produced them, rather than living in a separate silo. Safeguard closes that loop: container security scanning hardens images before they deploy and gives runtime signals the context of exactly what was in the image, so an unexpected process alert can be traced back to the package that shipped it. Griffin AI correlates runtime findings with known vulnerabilities and reachability data, so a detection on a container running a reachable, exploitable CVE is escalated over background noise — and it can drive remediation back into your pipeline. For the infrastructure controls that make detection cleaner, Safeguard's IaC scanning enforces read-only root filesystems, dropped capabilities, and network policies at review time. See how the full platform compares in Safeguard vs Aqua and on the comparison hub.
Detection and prevention work best together. Create a free Safeguard account or read the documentation to connect your environment.