Container and Kubernetes threat model

Container security has multiple distinct attack surfaces, each requiring different scanning approaches:

  • Base image vulnerabilities: CVEs in OS packages, language runtimes, and libraries included in the container image.
  • Kubernetes misconfigurations: Overly permissive pod security contexts, excessive RBAC permissions, missing network policies, exposed dashboards.
  • Supply chain compromise: Malicious or tampered base images, compromised container registries, unsigned images.
  • Runtime threats: Container breakout attempts, privilege escalation, lateral movement, cryptomining in pods.
  • Secrets in images or manifests: API keys or credentials embedded in Dockerfiles, environment variables in YAML, or baked into image layers.

Shift left and right: Container security requires both pre-deployment scanning (shift left β€” catch issues before they reach production) and runtime monitoring (shift right β€” detect threats in running environments). Neither alone is sufficient.

Container image scanning

Image scanning analyses container images for known CVEs in OS packages and application dependencies. It should run at every point where an image is built or pulled.

When to scan

  • At build time (CI): Scan the image immediately after it is built. Fail the pipeline on critical/high CVEs.
  • At push time: Scan again when pushing to the registry. Some registries (ECR, GCR, Docker Hub) offer built-in scanning on push.
  • Continuously in the registry: New CVEs are disclosed daily. An image that was clean last week may be vulnerable today. Schedule periodic rescans of images in the registry.
  • At deployment time: Admission controllers (OPA Gatekeeper, Kyverno) can block deployment of images that fail scanning policy.
Trivy image scanshell
# Scan a container image
trivy image --severity HIGH,CRITICAL myapp:latest

# Scan and output SARIF for GitHub Security tab
trivy image --format sarif --output results.sarif myapp:latest

# Fail CI if critical CVEs found
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# Scan a Dockerfile for misconfigurations too
trivy config Dockerfile

Distroless and minimal base images

Reducing the image footprint reduces the attack surface. Distroless images contain only the application and its runtime dependencies β€” no shell, no package manager, no unnecessary utilities. This dramatically reduces the number of CVEs in the base image and limits what an attacker can do after a container compromise.

Kubernetes manifest scanning

Kubernetes YAML manifests define how containers run β€” and many default configurations are insecure. Manifest scanning analyses deployment, pod, and other resource definitions for security misconfigurations before they reach the cluster.

Common Kubernetes misconfigurations

  • runAsRoot: true or no runAsNonRoot constraint β€” containers running as root
  • Missing readOnlyRootFilesystem: true β€” writable root filesystem enables persistence
  • privileged: true β€” effectively gives the container host access
  • Missing resource limits β€” enables CPU/memory DoS
  • hostNetwork: true, hostPID: true, hostIPC: true β€” breaks container isolation
  • Missing network policies β€” all pods can communicate by default
  • Missing seccompProfile β€” no syscall filtering
  • Secrets mounted as environment variables instead of volume mounts
secure-deployment.yamlYAML
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: app
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop: ["ALL"]
          resources:
            limits:
              cpu: "500m"
              memory: "128Mi"

Pod Security Standards (PSS)

Kubernetes 1.25+ ships with built-in Pod Security Admission, replacing the deprecated PodSecurityPolicy. Three security levels are defined:

  • Privileged: Unrestricted β€” allows known privilege escalation paths. Only for trusted system workloads.
  • Baseline: Minimally restrictive β€” prevents known privilege escalations while allowing typical containerised workloads. Good starting point.
  • Restricted: Follows current pod hardening best practices. Requires non-root execution, read-only root filesystem, capability dropping. Target for production workloads.
Enforce restricted PSS on a namespaceshell
# Label a namespace to enforce restricted PSS
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted

RBAC hardening

Kubernetes RBAC misconfigurations are a primary path for privilege escalation. Common issues:

  • Overly permissive ClusterRoles with * verbs or resources
  • Binding ServiceAccounts to cluster-admin
  • Default ServiceAccount tokens automounted in pods that do not need API access
  • Permissions to create pods, exec into pods, or escalate roles β€” all allow privilege escalation
Disable automounted service account tokenYAML
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
# Disable token automounting for SAs that don't need API access
automountServiceAccountToken: false

Runtime threat detection

Static scanning catches known vulnerabilities and misconfigurations before deployment. Runtime detection catches anomalous behaviour in running containers β€” zero-days, misconfigured allowlists, insider threats, and post-exploitation activity.

  • Falco: The leading open-source runtime security tool for Kubernetes. Uses eBPF or kernel module to monitor syscalls and detect anomalous behaviour β€” shell spawned in a container, file written to sensitive path, network connection to unexpected destination.
  • Tetragon (Cilium): eBPF-based security and observability. Provides process-level visibility with fine-grained policy enforcement at the kernel level.
  • Cloud provider solutions: AWS GuardDuty EKS Protection, GCP Security Command Center, Azure Defender for Containers all provide managed runtime detection with deep cloud integration.

CI/CD integration

.github/workflows/container-security.ymlYAML
name: Container Security Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Scan image with Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: '1'

      - name: Scan Kubernetes manifests
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: config
          scan-ref: k8s/
          exit-code: '1'

Tool comparison

Kubernetes security scanning toolstext
Tool          What it scans                     Type
──────────────────────────────────────────────────────────────────────
Trivy         Images, manifests, Dockerfiles     OSS, multi-purpose
Checkov       Kubernetes YAML, Helm, Terraform   OSS, IaC focus
kube-bench    Cluster CIS benchmark              OSS, node/cluster
kube-hunter   Penetration testing                OSS, active testing
Falco         Runtime syscall behaviour          OSS, runtime
Kubescape     Manifests + framework mapping      OSS, MITRE ATT&CK
AquilaX IaC  Manifests, Helm, Terraform, Docker Enterprise, CI/CD

Layered approach: Use Trivy or AquilaX for image and manifest scanning in CI, kube-bench to audit cluster configuration periodically, and Falco for runtime detection. Different tools catch different things β€” the layers complement each other.

Scan Kubernetes manifests and container images

AquilaX IaC scanning analyses Kubernetes YAML, Helm charts, and Dockerfiles for misconfigurations β€” integrated into your CI/CD pipeline in minutes.

Scan your Kubernetes configs β†’