CoursesRuntime & eBPF securityKernel hardening & isolation

seccomp syscall filtering

RuntimeDefault and custom default-deny profiles.

Advanced30 min · lesson 4 of 15

The first hardening control to reach for is seccomp — it shrinks the kernel attack surface a container can touch, which is exactly where escapes and post-exploitation live. A container that cannot call mount, ptrace, or keyctl has lost the tools for many escape techniques.

Syscall filtering with seccomp-BPF

seccomp (secure computing mode) filters which syscalls a process may make, using a BPF program that allows, denies, or errors on each call. A container typically needs only a few dozen of the ~350 syscalls; blocking the rest removes capabilities an attacker relies on without affecting the workload. Kubernetes and container runtimes ship a curated RuntimeDefault profile that blocks the dangerous syscalls while allowing normal workloads — and yet many clusters still run Unconfined, leaving the full syscall surface open.

apply RuntimeDefault and a custom profile
# Kubernetes: opt every pod into the curated default (do this by policy).
apiVersion: v1
kind: Pod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault # blocks ~44 dangerous syscalls; safe for most
# A tighter custom profile (Localhost) for a known workload: default-deny,
# allow only the syscalls the app actually uses.
{ "defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [{ "names": ["read","write","openat","connect","futex"],
"action": "SCMP_ACT_ALLOW" }] }

Building a profile that fits

RuntimeDefault is the right baseline for most workloads; for high-value services you can go tighter with a default-deny profile that allows only the syscalls the app makes, generated by recording a workload under a tracer or with the Security Profiles Operator. The tradeoff is maintenance — too tight and a code path breaks; too loose and you gain little. Start at RuntimeDefault everywhere (enforced by policy), then invest in bespoke profiles for the workloads that warrant it.

seccomp shrinks the syscall surface
1~350 syscalls available
Unconfined = all of them
2RuntimeDefault
blocks the dangerous set
3custom default-deny
allow only what the app uses
4smaller attack surface
fewer tools for escape/exploit
Every blocked syscall is a technique removed. RuntimeDefault as the floor, bespoke profiles for the crown jewels.
Unconfined leaves the whole kernel reachable
A container running with seccomp Unconfined can invoke every syscall, including the ones used in escape chains. Enforce at least RuntimeDefault across the cluster with admission policy — running Unconfined by default throws away one of the cheapest, highest-value container hardening controls.