Glossary/Detection Engineering/Container Security

What Is Container Security? The Build-Ship-Run Model

Container security is the set of controls that protect containerized workloads across their lifecycle, from the image you build through the registry, runtime, and orchestrator.

A container that runs as root with a writable filesystem and a hardcoded API token in its environment is one compromised process away from owning the node it sits on. The image was pulled from a public registry, never scanned, and rebuilt nightly from a latest tag nobody pinned. None of that is exotic. It is the default state of a container that no one secured, and it is what most container incidents trace back to: not a clever exploit, but a workload shipped with too much privilege, too many known vulnerabilities, and no one watching what it did at runtime.

Container security is the set of controls that protect containerized workloads across their entire lifecycle: the image you build, the registry you ship it from, the runtime where it executes, and the orchestrator that schedules it. This guide covers the build-ship-run model and the control at each stage, the threats those controls answer, NIST SP 800-190 as the reference framework, and the tooling that enforces it. It assumes you know what a container is; if not, start with the containerization primer. This piece is about securing them.

What is container security?

Container security is the practice of securing containerized applications at every point they can be attacked: the image and its dependencies, the registry that stores and distributes it, the running container and the host kernel it shares, and the orchestrator that decides where it runs and what it can reach. It is not a single product or a scan you run once. It is a discipline applied across a pipeline, because a container moves through distinct stages and each stage has its own attack surface.

The defining property of a container is that it shares the host kernel rather than booting its own. That is what makes containers fast and dense, and it is also the trade-off. A compromised virtual machine still has a hypervisor between it and the host. A compromised container is one kernel boundary, one misconfiguration, away from the host and every other container on it. So container security is about keeping that boundary intact and shrinking what a workload can do if it fails.

The clean way to reason about it is the lifecycle. An image is built, shipped to a registry, and run on a host under an orchestrator. Build, ship, run. Each stage takes a different control, and a gap at one stage undermines the others. A hardened runtime cannot save you from an image with a critical CVE in its base layer, and a scanned image cures nothing if the running container has every Linux capability and a path to the Docker socket.

Securing the image: build

The image is where most container risk is introduced, because everything that runs in production was put there at build time. Three failures dominate.

First, the base. An image is layers, and the bottom layer is a base you did not write. Pull ubuntu:latest and you inherit every package in it, most of which your application never uses, each a potential CVE. The control is a minimal, trusted base: distroless, Alpine, or a scratch image with only the binary and its runtime, pulled from a verified source rather than an arbitrary public tag. Less in the image means less to exploit and less to patch.

Second, vulnerabilities. The packages and dependencies you do include carry known CVEs that accumulate as the image ages. The control is to scan the image in the build pipeline and fail the build on findings above a severity threshold, so a critical CVE never reaches the registry. This is the highest-leverage control in the lifecycle, because it catches the most common root cause, a vulnerable image, before it ships.

Third, secrets. Developers bake API keys, passwords, and tokens directly into images, in an environment variable, a config file, or a layer deleted later but still readable in the image history. A secret in an image is a secret in the registry, readable by anyone who can pull it. The control is to keep secrets out of images and inject them at runtime from a secrets manager, and to scan images for embedded secrets the same way you scan for CVEs.

These map directly to NIST SP 800-190's image risks: image vulnerabilities, configuration defects, embedded clear-text secrets, and use of untrusted images. Securing the build is discipline encoded into the pipeline, not a tool bolted on later.

Securing the registry: ship

The registry is the distribution point: every host that runs your image pulls it from here, so the registry is both a chokepoint to control and a target to protect. Two controls matter.

Access control. A registry that anyone can push to is a registry an attacker can poison, replacing a trusted image with a backdoored one that every node then pulls and runs. Lock down who can push and who can pull, use separate credentials per environment, and never leave a registry world-writable or world-readable for images that are not meant to be public.

Image signing and verification. Access control says who may push; signing proves what they pushed is what runs. Sign images at build time and verify the signature before a host runs them, so a tampered or unsigned image is rejected at admission. This closes the gap where an attacker with registry access, or a man in the middle, swaps the image between push and pull. NIST SP 800-190's registry risks are exactly these: insecure connections to registries, stale images with known vulnerabilities sitting in the registry long after they should have been pulled, and insufficient authentication and authorization on who can push and pull.

Securing the runtime: run

Build and ship controls reduce what enters the environment. Runtime controls reduce what a container can do once it is running, on the assumption that something will eventually go wrong inside it. The principle is least privilege applied to the workload, with a few concrete levers.

Run as non-root. A container running as root runs as a user that, if it escapes, is root on the host. Set a non-root user in the image and enforce it at runtime. This one change defuses a large class of container-escape and privilege-escalation paths.

Read-only filesystem. A container that cannot write to its own filesystem cannot have a payload dropped into it or modify its own binaries, and forces an attacker to work in memory. Mount the root filesystem read-only and grant writable space only where the application needs it, as a named volume or tmpfs.

Drop capabilities. Linux capabilities split root's power into units like CAP_NET_RAW and CAP_SYS_ADMIN. A container gets a default set it almost never fully needs. Drop all capabilities and add back only the few the workload requires. CAP_SYS_ADMIN in particular is close to full root and should almost never be present.

Confine syscalls and behavior. A seccomp profile restricts which Linux system calls a container may make, shrinking the kernel attack surface container escapes depend on. AppArmor or SELinux profiles confine what files and capabilities the process can touch. The default Docker seccomp profile already blocks dozens of dangerous syscalls; the failure mode is running with --privileged or seccomp=unconfined, which throws all of it away.

Runtime threat detection. Hardening reduces the odds; detection tells you when something got through anyway. A runtime sensor watches the container's actual behavior, a shell spawned where one should never run, an outbound connection to an unexpected host, a write to a sensitive path, and alerts on it. Without it, a container escape or a cryptojacking payload runs silently. NIST SP 800-190's container risks cover this ground: vulnerabilities in the runtime software, unbounded network access, insecure runtime configurations, and rogue containers running unmonitored.

Securing the orchestrator: Kubernetes

At scale you do not run containers by hand, you run them under an orchestrator, and Kubernetes is the one most environments use. The orchestrator is a high-value target because it controls everything: a foothold on the Kubernetes control plane is a foothold on every workload it schedules. Four controls anchor orchestrator security.

RBAC. Kubernetes role-based access control governs what every user and service account can do against the API server. The default failure is over-broad roles, a service account bound to cluster-admin that only needed to read one namespace. Scope roles to the minimum, like any other least-privilege problem.

Network policies. By default every pod can talk to every other pod, so one compromised pod has the reach to scan and pivot across the whole cluster. Network policies restrict pod-to-pod traffic to what is needed, turning a flat internal network into segmented paths and cutting off the lateral movement an attacker depends on after the first foothold.

Pod Security Standards. Kubernetes Pod Security Standards define three policy levels, privileged, baseline, and restricted, that constrain what a pod may request: whether it can run as root, mount the host filesystem, use host networking, or run privileged. Enforcing the restricted profile makes the runtime hardening above mandatory rather than a per-team convention.

Secrets management. Kubernetes Secrets are base64-encoded, not encrypted, by default, so a Secret readable by an over-privileged pod or stored in plaintext etcd is a credential leak waiting to happen. Encrypt secrets at rest, restrict which service accounts can read them, and prefer an external secrets manager for high-value credentials. NIST SP 800-190's orchestrator risks line up here: unbounded administrative access, unauthorized access to the orchestrator, poorly separated inter-container network traffic, and mixing workload trust levels on one host.

The build-ship-run controls at a glance

Container Security Lifecycle
Build, ship, run
A control at every stage, plus the orchestrator that schedules it all
01 BUILD
Secure the image
Minimal trusted base. Scan for CVEs. No secrets baked in.
02 SHIP
Secure the registry
Sign and verify images. Lock down who can push and pull.
03 RUN
Secure the runtime
Non-root. Read-only FS. Drop capabilities. seccomp. Runtime detection.
Across all stages: the orchestrator Kubernetes RBAC, network policies, Pod Security Standards (restricted), and secrets management. The control plane schedules every workload, so a foothold there reaches them all.

The lifecycle is the spine of container security. Each stage carries a characteristic risk and a control that answers it. The table maps them, with the NIST SP 800-190 risk category each falls under.

StagePrimary riskControlNIST SP 800-190 category
BuildVulnerable or bloated base imageMinimal trusted base; scan for CVEs; no baked-in secretsImage risks
ShipTampered or unsigned image in the registryImage signing and verification; registry access controlRegistry risks
RunOver-privileged container, container escapeNon-root; read-only FS; drop capabilities; seccomp/AppArmor; runtime detectionContainer risks
OrchestrateOver-broad cluster access, lateral movementRBAC; network policies; Pod Security Standards; secrets managementOrchestrator risks
HostShared kernel, unpatched hostPatch the host; minimal host OS; isolate workload trust levelsHost OS risks

The point of the table is that the controls are cumulative, not alternatives. You do not pick one stage to secure. A scanned, signed image still needs to run non-root under a network policy, because the threats arrive at different stages and a single missing control is the gap an attacker uses.

The threats container security answers

Five attack patterns recur, and each maps to a control above that, when absent, lets it happen.

Vulnerable images. The most common entry point. An image ships with a known CVE in a dependency, the workload is internet-facing, and the exploit is public. The control is build-time scanning and minimal bases.

Container escape. The attacker breaks out to the host kernel, usually through a privileged container, an over-granted capability like CAP_SYS_ADMIN, a writable host mount, or a kernel vulnerability the seccomp profile would have blocked. Once on the host, every container on it is reachable. Non-root, dropped capabilities, read-only mounts, and seccomp close these paths.

Exposed Docker and Kubernetes APIs. An unauthenticated Docker daemon socket or Kubernetes API server exposed to the network is remote code execution by design: anyone who reaches it can schedule containers, mount the host, and run as root. Internet scanners find these within minutes of exposure. Authentication, RBAC, and not exposing the control plane are the answer.

Lateral movement. After the first foothold, a flat pod network lets the attacker move from the compromised workload to others, reaching databases, secrets, and the control plane. Network policies and segmentation break the chain.

Cryptojacking. The quiet one. An attacker who lands in a container often does not exfiltrate data, they mine cryptocurrency on your compute, which is why it runs undetected for so long. Runtime detection that flags an unexpected process or outbound connection is usually how it gets caught, because the workload shows no functional symptom.

NIST SP 800-190: the reference framework

When you need a structured, vendor-neutral model for container security, the reference is NIST SP 800-190, the *Application Container Security Guide*, published in September 2017. It organizes container risk into five categories that map almost exactly onto the lifecycle: image risks, registry risks, orchestrator risks, container risks, and host OS risks. For each it states the risk and the countermeasure, which is why it has aged well despite predating much of the current tooling: the categories are structural, not tool-specific.

Used as a checklist, SP 800-190 keeps a program honest. It is easy to scan images (image risks) and call container security done while the runtime is unconfined (container risks) and the orchestrator is wide open (orchestrator risks). Walking the five categories forces coverage across the whole stack rather than the one stage a team finds easiest. It pairs naturally with the broader cloud-native security practices that govern the platform the containers run on.

Tooling: what enforces the controls

The controls above are enforced by a few categories of tooling, and none replaces the others.

Image scanners. Trivy, an open-source scanner from Aqua Security, scans images for known CVEs, misconfigurations, and embedded secrets, and runs in the build pipeline to fail builds on findings. Grype and Clair fill the same role. This is the build-stage workhorse.

Admission control. An admission controller sits between a deployment request and the cluster and rejects anything that violates policy: an unsigned image, a privileged pod, a root container. Open Policy Agent Gatekeeper and Kyverno are the common engines, and Pod Security Standards admission is built into Kubernetes. This is where ship and run policy becomes a hard gate rather than a guideline.

Runtime detection. Falco, a graduated CNCF project originally built by Sysdig, watches Linux system calls and Kubernetes audit events at runtime and alerts on suspicious behavior: a shell in a container, a sensitive file read, an unexpected outbound connection. It is the sensor that catches container escape, cryptojacking, and post-exploitation activity the build and ship controls cannot.

Cloud workload protection platforms. A cloud workload protection platform (CWPP) bundles these capabilities, vulnerability scanning, runtime protection, configuration hardening, and compliance, into one platform covering containers alongside VMs and serverless workloads. It is the consolidated path for teams that do not want to assemble and operate the individual tools.

The bottom line

Container security is the lifecycle, secured end to end. Build a minimal, trusted image, scan it for CVEs, and keep secrets out of it. Ship it from a registry with access control and signature verification so what runs is what you built. Run it with least privilege: non-root, read-only filesystem, dropped capabilities, a seccomp profile, and a runtime sensor watching for what gets through. Orchestrate it under RBAC, network policies, Pod Security Standards, and real secrets management.

The threats, vulnerable images, container escape, exposed APIs, lateral movement, cryptojacking, are not exotic. Each maps to a control that, when present, would have stopped it, and when absent, is the gap. NIST SP 800-190's five risk categories are the checklist that forces coverage across all of it instead of the one stage a team finds easiest. Secure every stage, because an attacker only needs the one you skipped.

Frequently asked questions

What is container security?

<p>Container security is the set of controls that protect containerized workloads across their lifecycle: the image you build, the registry you ship it from, the runtime where it executes, and the orchestrator that schedules it. Because a container shares the host kernel, the central goal is keeping that boundary intact and limiting what a workload can do if it is compromised. It is a discipline applied across a pipeline, not a single product.</p>

What is the build-ship-run model in container security?

<p>Build, ship, run is the lifecycle a container moves through, and each stage takes a different control. Build secures the image with a minimal trusted base, CVE scanning, and no baked-in secrets. Ship secures the registry with image signing and access control. Run secures the live container with non-root execution, a read-only filesystem, dropped capabilities, and runtime detection. A gap at any stage undermines the others.</p>

What is a container escape?

<p>A container escape is when an attacker breaks out of a container to the underlying host, gaining access to the host kernel and every other container on it. It usually exploits a privileged container, an over-granted Linux capability like <code>CAP_SYS_ADMIN</code>, a writable host mount, or a kernel bug. Running as non-root, dropping capabilities, mounting the filesystem read-only, and applying a seccomp profile are the controls that close these paths.</p>

What does NIST SP 800-190 cover?

<p>NIST SP 800-190, the Application Container Security Guide published in September 2017, is the reference framework for container security. It organizes risk into five categories that map onto the lifecycle: image risks, registry risks, orchestrator risks, container risks, and host OS risks. For each it states the risk and the countermeasure, which makes it a durable checklist for verifying coverage across the whole stack.</p>

How do you secure a Kubernetes cluster?

<p>Secure a Kubernetes cluster with four controls. Scope RBAC so users and service accounts hold only the minimum permissions against the API server. Apply network policies so pods cannot freely talk to every other pod. Enforce Pod Security Standards, ideally the restricted profile, to block privileged and root pods. And manage secrets properly, since Kubernetes Secrets are only base64-encoded by default, so encrypt them at rest and restrict which accounts can read them.</p>

What is Falco used for?

<p>Falco is a graduated CNCF runtime security tool, originally built by Sysdig, that watches Linux system calls and Kubernetes audit events and alerts on suspicious behavior in real time: a shell spawned inside a container, a sensitive file read, an unexpected outbound connection. It is the detection layer that catches container escapes, cryptojacking, and post-exploitation activity that build-time and registry controls cannot see.</p>

Practice track
SOC Analyst Tier 1
Build your foundational skills to monitor, detect, and escalate security alerts. This track includes essential tools, basic log analysis, and introductory incident response labs.
Browse SOC Analyst Tier 1 Labs โ†’