seccomp: filter syscalls
RuntimeDefault and a curated custom profile.
A container talks to the host kernel through syscalls, and a kernel bug reachable through an exotic syscall is a direct route out. seccomp (secure computing mode) filters which syscalls a process may make. Docker ships a default profile that already blocks dozens of dangerous calls (mount, ptrace, kernel module loading, and more) — but the critical caveat is that --privileged and some runtimes run unconfined, so “the default is on” is an assumption to verify.
# confirm the default seccomp profile is actually applied (Docker’s default: on)$ docker run --rm alpine grep Seccomp /proc/self/statusSeccomp: 2 # 2 = filter mode active. 0 = UNCONFINED (bad)# --privileged disables it entirely:$ docker run --rm --privileged alpine grep Seccomp /proc/self/statusSeccomp: 0 # no syscall filtering at all
A custom profile for a tight allowlist
To go beyond the default, ship a JSON profile that denies by default and allows only the syscalls your app makes. You do not guess the list — you observe it: run under an audit (log-only) profile, exercise every code path, and read which syscalls were actually used, then allow exactly those. The result is a container that can make a few dozen syscalls instead of the ~300 the kernel exposes.
# 1) discover the syscalls the app really uses$ strace -f -qcf -o trace.txt myapp # or run under an SCMP_ACT_LOG profile# 2) apply a curated profile that allows only those$ docker run --rm --security-opt seccomp=./app-seccomp.json myapp:1.0
{"defaultAction": "SCMP_ACT_ERRNO", // deny everything..."architectures": ["SCMP_ARCH_X86_64"],"syscalls": [{"names": ["read","write","openat","close","futex","epoll_wait","accept4"],"action": "SCMP_ACT_ALLOW" // ...except this observed allowlist}]}