← Back to all posts
10 min readKishin

Container Security: Protecting Kubernetes and Docker Workloads

SecurityContainers

Containers have transformed how organizations build, ship, and run software. Docker and Kubernetes have become the de facto standards for containerized application deployment, enabling rapid scaling, consistent environments, and efficient resource utilization. But this speed and flexibility come with a unique set of security challenges that traditional perimeter-based defenses were never designed to address. Containers introduce a multi-layered attack surface spanning the image build pipeline, the orchestration platform, and the runtime environment. Securing containerized workloads demands a defense-in-depth approach that addresses each layer independently and collectively.

Docker Security Pitfalls

Docker makes it trivially easy to package and distribute applications, but ease of use often comes at the expense of security. The most common Docker security pitfalls include running containers as root, relying on the latest tag, building bloated images, embedding secrets in image layers, and deploying unscanned base images.

Running as Root

By default, Docker containers run processes as the root user inside the container. While container isolation provides some separation from the host kernel, a container escape vulnerability combined with root privileges gives an attacker immediate root access on the host. Every Dockerfile should include a USER directive that specifies a non-root user. If your application requires elevated privileges, use Linux capabilities to grant only the specific permissions needed rather than full root access. The principle of least privilege applies just as strongly inside containers as it does in traditional environments.

The Latest Tag Trap

Using the :latest tag in production is a security anti-pattern. The latest tag is mutable, meaning the image it points to changes over time. This creates two problems: it makes your deployments non-reproducible, and it allows potentially untested or compromised images to be pulled into production. Always pin image versions to specific digests or immutable tags. Implement an image promotion workflow where images progress through development, staging, and production with explicit versioning at each stage.

Large Attack Surface Images

The default Docker base images for many languages and frameworks include dozens of packages, utilities, and libraries that your application never uses. Each unused package is a potential vulnerability. Use minimal base images like Alpine Linux or distroless images from Google. A distroless image contains only the runtime and its dependencies: no shell, no package manager, no unnecessary utilities. This dramatically reduces the attack surface and the number of CVEs that scanners will flag.

Exposed Secrets in Image Layers

Docker images are built in layers, and every layer is cached and stored independently. If you add a secret in one layer and remove it in a subsequent layer, the secret still exists in the earlier layer. Attackers who gain access to the image registry can extract API keys, database passwords, and private keys from these hidden layers. Use Docker BuildKit secrets mounts, which pass secrets to the build process without writing them to any layer. Alternatively, fetch secrets at runtime from a vault service like HashiCorp Vault or AWS Secrets Manager.

Unscanned Base Images

Base images from public registries like Docker Hub frequently contain known vulnerabilities. If you pull a base image once and never update it, you are running code with known exploits available in the wild. Integrate vulnerability scanning into your CI/CD pipeline so that every image build is automatically assessed for CVEs. Establish a policy that blocks deployment of images with critical or high-severity vulnerabilities.

Kubernetes Security

Kubernetes adds a powerful orchestration layer on top of containers, but it also introduces its own complex attack surface. Securing Kubernetes requires attention to access control, network isolation, secrets management, admission policies, and runtime behavior.

RBAC Misconfigurations

Role-Based Access Control in Kubernetes governs who can do what within the cluster. A common misconfiguration is granting cluster-wide permissions when namespace-scoped permissions would suffice. Wildcard permissions on resources and verbs effectively make users cluster administrators. Audit your RBAC configurations regularly using tools like kubeaudit or rakkess. Follow the principle of least privilege: grant only the minimum permissions needed for each role, and prefer Role and RoleBinding over ClusterRole and ClusterRoleBinding whenever possible.

Pod Security Standards

Kubernetes Pod Security Standards (PSS) define three security levels: Privileged, Baseline, and Restricted. The Restricted profile enforces the strictest controls, preventing privilege escalation, requiring non-root users, disallowing host filesystem access, and limiting Linux capabilities. Implement PSS at the namespace level using Pod Security Admission, which replaced the deprecated PodSecurityPolicy. Namespace-level enforcement ensures that all pods created in a given namespace must meet a minimum security baseline.

Network Policies for Pod-to-Pod Communication

By default, Kubernetes allows all pod-to-pod communication across the cluster. This flat network model means that a compromised pod can communicate with every other pod, including databases, internal APIs, and other sensitive services. Network Policies act as firewall rules for Kubernetes pods, restricting ingress and egress traffic based on namespace selectors, pod labels, and IP ranges. Implement a default-deny Network Policy in every namespace and explicitly allow only the traffic patterns your applications require.

Secrets Management

Kubernetes Secrets are base64-encoded by default, not encrypted. They are stored in etcd, the cluster’s backing datastore, in plaintext unless etcd encryption is explicitly configured. Even with etcd encryption enabled, secrets are available in cleartext to anyone with API access. For production workloads, consider external secrets management solutions like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault, integrated via the Secrets Store CSI Driver. Rotate secrets regularly and audit access to sensitive data.

Admission Controllers

Admission controllers intercept requests to the Kubernetes API server before objects are persisted. They can validate requests against policies, mutate objects to inject security defaults, or reject non-compliant configurations. Tools like OPA Gatekeeper and Kyverno enable policy-as-code enforcement across the cluster. Use admission controllers to enforce image provenance (only images from trusted registries), require resource limits, inject sidecar containers for logging or monitoring, and block privileged containers.

Runtime Security with Falco and Sysdig

Runtime security monitors container behavior in real time to detect anomalies that indicate compromise. Falco, the CNCF runtime security project, uses eBPF or kernel modules to observe system calls and alerts on suspicious activity such as shell spawning inside a container, unexpected network connections, sensitive file reads, or privilege escalation attempts. Sysdig extends Falco with commercial features including automated response actions, compliance dashboards, and threat intelligence feeds. Runtime detection is your last line of defense against attacks that bypass static controls.

API Server Exposure

The Kubernetes API server is the brain of the cluster. Exposing it to the internet without strong authentication and authorization is equivalent to leaving the keys to your entire infrastructure in a public place. Ensure the API server is accessible only from trusted networks, enforce mutual TLS authentication, disable anonymous authentication, and audit all API calls. Use kube-bench to validate that your cluster configuration complies with the CIS Kubernetes Benchmark.

Image Supply Chain Security

The integrity of your container images determines the integrity of your applications. Supply chain attacks that compromise base images, build tools, or registries can inject malicious code into every downstream deployment.

Private Registries

Public registries are convenient but risky. They are frequent targets for typosquatting attacks, where malicious images are published with names similar to popular projects. Use private registries for all production images. Implement admission policies that block pulls from public registries. Scan images as they are pushed to the private registry and enforce image provenance tracking.

Image Signing with Cosign and Notary

Image signing provides cryptographic proof that an image was built by a trusted source and has not been tampered with. Cosign, part of the Sigstore project, enables keyless signing using OIDC identity and stores signatures in the OCI registry alongside the image. Notary (v2, based on the TUF framework) provides a similar capability. At deployment time, admission controllers can verify signatures before allowing pods to start, creating a trusted pipeline from build to runtime.

Vulnerability Scanning in CI/CD

Integrating vulnerability scanning into your CI/CD pipeline ensures that no image reaches production without a security assessment. Trivy and Grype are open-source scanners that detect OS-level and application-level vulnerabilities in container images. Configure your pipeline to fail builds that introduce critical-severity CVEs. Scan base images on a regular schedule, not just during builds, because new vulnerabilities are discovered daily.

SBOM Generation

A Software Bill of Materials (SBOM) provides a complete inventory of every component, library, and dependency in your container image. When a new vulnerability like Log4Shell is announced, an SBOM lets you instantly determine which images are affected without rescanning. Tools like Syft generate SBOMs in standard formats like SPDX and CycloneDX. Attach SBOMs to your images as OCI attestations so they travel with the image through the supply chain.

Runtime Protection

Static scanning and policy enforcement catch known risks, but runtime protection addresses the unknown: the zero-day exploit, the insider threat, the novel attack technique. Container isolation, mandatory access control profiles, and behavioral monitoring form the runtime defense layer.

Container Isolation

Containers share the host kernel, which means a kernel vulnerability in one container can compromise the entire host. Use gVisor or Kata Containers to add an additional isolation layer between containers and the host kernel. gVisor intercepts system calls and provides its own kernel-like interface, while Kata Containers run each workload in a lightweight virtual machine. These technologies reduce the blast radius of a container escape to a single workload.

Seccomp and AppArmor Profiles

Seccomp (Secure Computing Mode) restricts the system calls a container can make, while AppArmor confines processes based on security profiles. Kubernetes ships with a default seccomp profile that blocks dangerous syscalls, but it is not enabled by default. Enable the RuntimeDefault seccomp profile on all pods. For high-security workloads, create custom seccomp profiles that whitelist only the syscalls the application actually needs. AppArmor profiles add another layer by restricting file access, network operations, and capability usage.

Monitoring for Anomalous Behavior

Behavioral monitoring complements signature-based detection by establishing a baseline of normal container activity and alerting on deviations. Unexpected outbound connections, sudden spikes in CPU or memory, file writes to sensitive paths, or new process execution inside a container can all indicate compromise. Combine Falco rules with your SIEM or observability platform to create correlated alerts that distinguish real threats from noise. The goal is to detect the attacker who bypasses your static controls before they achieve their objective.

Conclusion

Container security is not a single product or a single policy: it is a continuous discipline that spans the entire lifecycle from image creation to runtime monitoring. Organizations that treat containers as ephemeral and therefore unimportant are making a dangerous assumption. Containers are the new compute unit, and they deserve the same security rigor that you apply to virtual machines and bare metal servers. Start with image hygiene and supply chain integrity, harden your orchestration platform, and deploy runtime detection to catch what gets through. The attackers are already exploiting container weaknesses. Your defenses must be ready.