Skip to content

🛡️ Container Hardening

Container Hardening is the process of reducing the attack surface of containers by applying security best practices to container images, runtimes, orchestrators, and host systems. The goal is to make containers more resistant to compromise while maintaining functionality.

A hardened container follows the principle of:

“Provide only the minimum software, permissions, and access required to run the application.”

This aligns with the security concepts of:

  • Least Privilege
  • Defense in Depth
  • Secure by Default
  • Zero Trust

Containers share the host operating system kernel. If an attacker compromises a container, weaknesses in configuration may allow them to:

  • Escape the container
  • Access sensitive data
  • Move laterally to other containers
  • Compromise the host
  • Gain cluster-wide control

Proper hardening significantly reduces these risks.


FROM ubuntu:latest

Contains many unnecessary packages.

FROM alpine:3.22
FROM gcr.io/distroless/dotnet

or

FROM scratch

Benefits:

  • Smaller attack surface
  • Fewer vulnerabilities
  • Faster image downloads
  • Less software to patch

Avoid installing tools not required by the application.

RUN apt-get install -y \
vim \
curl \
net-tools \
telnet

Install only what is needed:

RUN apt-get install -y ca-certificates

Many containers run as root by default.

FROM nginx
RUN adduser --system appuser
USER appuser

Or in Kubernetes:

securityContext:
runAsNonRoot: true
runAsUser: 1001

Benefits:

  • Limits privilege escalation
  • Reduces container breakout impact

Most applications do not need to write to the container filesystem.

Kubernetes:

securityContext:
readOnlyRootFilesystem: true

Benefits:

  • Prevents malware installation
  • Protects application binaries

Linux capabilities provide privileged actions.

Containers often receive capabilities they do not need.

securityContext:
capabilities:
drop:
- ALL

Add back only required ones:

securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE

Common dangerous capabilities:

  • SYS_ADMIN
  • SYS_MODULE
  • NET_ADMIN
  • SYS_PTRACE

Kubernetes:

securityContext:
allowPrivilegeEscalation: false

Prevents processes from gaining additional privileges.


securityContext:
privileged: true

This effectively gives the container host-level access.

Only use when absolutely necessary.


Use security scanners to detect:

  • CVEs
  • Outdated libraries
  • Misconfigurations
  • Secrets

Popular tools:

  • Trivy
  • Snyk
  • Grype
  • Microsoft Defender for Containers
  • Docker Scout

Example:

trivy image myapp:latest

Ensure container images are trusted.

Tools:

  • Cosign
  • Notary
  • Sigstore

Example:

cosign sign myapp:1.0

Benefits:

  • Prevents supply-chain attacks
  • Verifies image authenticity

Avoid:

FROM node:16

if no longer supported.

Regularly:

  • Update base images
  • Rebuild containers
  • Patch dependencies

Automate through CI/CD pipelines.


ENV DB_PASSWORD=SuperSecret123
  • Kubernetes Secrets
  • Azure Key Vault
  • AWS Secrets Manager
  • HashiCorp Vault

Secrets should never be baked into images.


Limit communication between containers.

Example Kubernetes Network Policy:

kind: NetworkPolicy
spec:
podSelector:
policyTypes:
- Ingress
- Egress

Benefits:

  • Reduces lateral movement
  • Limits blast radius

Prevent resource exhaustion attacks.

resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"

Protects against:

  • Denial of Service (DoS)
  • Runaway processes
  • Cryptocurrency miners

Seccomp restricts Linux system calls.

Example:

securityContext:
seccompProfile:
type: RuntimeDefault

Benefits:

  • Reduces kernel attack surface
  • Blocks dangerous syscalls

Additional mandatory access controls.

Examples:

container.apparmor.security.beta.kubernetes.io/app: runtime/default
securityContext:
seLinuxOptions:
level: "s0:c123,c456"

Provides another layer of isolation.


ControlRecommendation
Base ImageUse distroless or minimal images
UserRun as non-root
PrivilegesDisable privileged mode
FilesystemRead-only where possible
CapabilitiesDrop all unnecessary capabilities
SecretsUse Vault/Key Vault/K8s Secrets
Image ScanningScan for CVEs continuously
Resource LimitsSet CPU and memory limits
NetworkUse network policies
SeccompEnable RuntimeDefault
AppArmor/SELinuxEnforce policies
Image SigningVerify trusted images
UpdatesPatch and rebuild often

apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
containers:
- name: app
image: myapp:1.0
securityContext:
runAsNonRoot: true
runAsUser: 10001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
resources:
limits:
cpu: "1"
memory: "512Mi"

In summary:

Container Hardening is the practice of securing containerized applications by minimising the attack surface, reducing privileges, and enforcing security controls. Common hardening measures include using minimal base images, running containers as non-root users, removing unnecessary packages, dropping Linux capabilities, enabling Seccomp/AppArmor, scanning images for vulnerabilities, managing secrets securely, and restricting network access. The objective is to prevent container compromise and limit the impact if a breach occurs.