Container Security
From layer 0 to the running process
Defense in depth across image → runtime → cluster: least-privilege images, scanning + signing gating, seccomp/AppArmor/SELinux profiles, read-only roots, non-root users, and runtime threat detection.
What you will learn
- Harden image content before it exists (bases, non-root, scans)
- Constrain runtime: capabilities, seccomp, read-only
- Detect and respond to in-container threats
Attack surface = image (bugs in packages, secrets, supply chain) × runtime (syscalls, capabilities) × error. You shrink each: slimmer bases, scan+sign gates, drop caps, seccomp defaults, non-root UID, read-only root, and runtime monitoring.
What is this?
Image phase: OSV/base selection, scanning (Trivy/Grype/Clair), signing (cosign), provenance+SBOM, minimal binaries, distroless. Runtime phase: non-root USER, drop ALL then add, seccomp/AppArmor/SELinux profiles, read-only rootfs, no-new-privileges, IPC/PID isolation, resource limits. Cluster/admission: Kyverno/OPA policies for default-deny on crowd, signed-image verification, Node Y / privileged-pod denial, PBAC. Detection: Falco/tracee/malware scanner rules on abnormal syscalls, excessive exec in pods, new binaries.
Why do you need it?
- Containers share the host kernel: a container exploit is an escape attempt if seccomp/caps leak.
- Supply-chain poisoning via a big base image is a real, verified attack path.
- Capabilities/seccomp defaults stop 90% of classic syscall privilege escalation.
- Read-only roots + non-root change a CI/API exploit from control to crash.
Mental model
A factory floor: employees have badges, tools, and a closed permit room
Least privilege in containers
Workers (processes) carry only the badges (capabilities) they need; the permit room (privileged syscalls) is locked (seccomp), and janitors don't have manager keys (non-root).
How it works
- Admission policies reject images lacking signatures/approvals and securityContext mandates.
- Non-root USER applies; no-new-privs + dropping caps hardens the process.
- Seccomp whitelist shrinks syscalls; AppArmor/SELinux constrain fs/network/proc access.
- read-only rootfs + tmpfs for scratch stops persistence of dropped malware.
- Falco-style rules watch execv, network egress and filesystem writes for anomalies → alerts/block.
Layered container defense.
Examples
A hardened securityContext (K8s)
securityContext: runAsNonRoot: true runAsUser: 65532 readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: [ALL] seccompProfile: { type: RuntimeDefault }Together: no root, no writes, no privilege gain, no native capabilities, default seccomp. That's your baseline slice of the attack surface gone.
In production
- Every prod image non-root + distroless/slim; scan gates fail unsafe pushes.
- Admission policy: signed images only; no privileged containers cluster-wide.
- Falco monitoring flagged unexpected /bin/sh in a worker → immediate pod kill + incident.
- Image SBOM emitted at build, diffed against CVE feeds for registry policy.
Best practices
- Choose minimal base; strip shells/tools that only debugging (not prod) uses.
- Enforce non-root, drop ALL capabilities, read-only root at the platform (admission), not per-Dockerfile hope.
- Scan on push + gate; re-scan when feeds update to catch new CVEs.
- Lock down runtime syscalls with seccomp default unsuppressed.
- Make detection first-class: Falco/tracee logs into the SIEM and page on anomalies.
Common mistakes
- Running as root 'just this one’ app while exposing the host kernel.
- Secrets in images that scanning later finds 'in production bytes'.
- Admission-time blessing only of tag names, not digests+signatures.
- Assuming scanning alone = secure (they only see known CVEs, run-time evasion is separate).
Debugging tips
- Functionality breaks under hardened securityContext → read the seccomp/capability error; add precisely what's missing.
- Permission denied writing → read-only rootfs + your app assumes /tmp — mount tmpfs explicitly.
- Falco false positives → be specific: exemptions by workload/image label.
- Image X still vulnerable → distinguish base-image vs installed-package vs dependency scans.
Interview checkpoint
Hands-on lab
- Run an image hardened with seccomp/caps/non-root/read-only root
- Confirm capabilities and syscalls are reduced
- Show what breaks (and why) before/after hardening
Harden a Container and Prove the Drop
45 min · advanced
Quick quiz
Which default stops most container escapes?
Image scanning deals with: