- Published on
Container Security & Supply Chain Complete Guide 2025: Image Scanning, Sigstore, SBOM, Runtime Security
- Authors

- Name
- Youngju Kim
- @fjvbn20031
Table of Contents
1. Container Threat Model: Understanding the Attack Surface
Container environments have a unique threat surface distinct from traditional VM-based infrastructure. A multi-layered security strategy is needed covering image vulnerabilities, misconfigurations, runtime attacks, and supply chain threats.
1.1 Container Attack Surface
Container Security Layers:
┌─────────────────────────────────────────────────┐
│ Layer 6: Supply Chain │
│ - Base image poisoning, dependency tampering │
├─────────────────────────────────────────────────┤
│ Layer 5: Orchestration (Kubernetes) │
│ - Missing RBAC, exposed API server, unencrypted │
├─────────────────────────────────────────────────┤
│ Layer 4: Network │
│ - Missing network policies, no service mesh │
├─────────────────────────────────────────────────┤
│ Layer 3: Runtime │
│ - Container escape, privilege escalation, mining │
├─────────────────────────────────────────────────┤
│ Layer 2: Image │
│ - CVEs, hardcoded secrets, excessive packages │
├─────────────────────────────────────────────────┤
│ Layer 1: Host OS / Container Runtime │
│ - Kernel vulns, Docker socket exposure, runc │
└─────────────────────────────────────────────────┘
1.2 Key Attack Vectors
1. Image Vulnerability Exploitation:
Attacker -> Exploit known CVEs in public images -> Container compromise
2. Supply Chain Attack:
Attacker -> Inject malware in base image/library -> Downstream poisoning
3. Runtime Attack:
Attacker -> Exploit vulnerable app -> Container escape -> Host access
4. Misconfiguration Exploitation:
Attacker -> Excessive permissions/missing policies -> Lateral movement
2. Image Security: Building Secure Container Images
2.1 Choosing Minimal Base Images
# BAD: Full image (200MB+, potentially hundreds of CVEs)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY app.py /app/
CMD ["python3", "/app/app.py"]
# GOOD: Distroless image (minimal binaries only)
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
FROM gcr.io/distroless/python3-debian12
COPY /app /app
COPY /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
WORKDIR /app
CMD ["app.py"]
2.2 Chainguard Images
# Chainguard Images: rebuilt daily, zero-CVE goal
FROM cgr.dev/chainguard/python:latest-dev AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
FROM cgr.dev/chainguard/python:latest
COPY /app /app
COPY /home/nonroot/.local/lib/python3.12/site-packages /home/nonroot/.local/lib/python3.12/site-packages
WORKDIR /app
ENTRYPOINT ["python", "app.py"]
2.3 Multi-Stage Builds and Security
# Go app multi-stage build
FROM golang:1.22-alpine AS builder
# Security: install build-only tools
RUN apk add --no-cache git ca-certificates
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Security: static binary (CGO disabled)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-w -s" -o /app/server ./cmd/server
# Final image: scratch (completely empty)
FROM scratch
# Security: non-root user
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY /etc/passwd /etc/passwd
COPY /app/server /server
USER 65534:65534
ENTRYPOINT ["/server"]
2.4 Dockerfile Security Best Practices
# Security-hardened Dockerfile
FROM node:20-slim AS builder
# Security: create non-root user
RUN groupadd -r appuser && useradd -r -g appuser -d /app appuser
WORKDIR /app
# Security: copy package.json first (layer caching)
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --production
COPY . .
RUN yarn build
# Production image
FROM node:20-slim
# Security: non-root user
RUN groupadd -r appuser && useradd -r -g appuser -d /app appuser
WORKDIR /app
# Security: copy only necessary files
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY /app/package.json ./
# Security: run as non-root
USER appuser
# Security: read-only filesystem compatible
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/index.js"]
3. Image Scanning: Vulnerability Detection
3.1 Scanning Tool Comparison
| Tool | License | Features | CI/CD Integration | SBOM Generation |
|---|---|---|---|---|
| Trivy | Apache 2.0 | Comprehensive scanner (image/IaC/secrets) | Excellent | Supported |
| Grype | Apache 2.0 | Fast vulnerability scan | Excellent | syft integration |
| Docker Scout | Premium | Docker Desktop integration | Docker Hub | Supported |
| Snyk Container | Premium | Excellent fix recommendations | Excellent | Supported |
3.2 Using Trivy
# Image scan
trivy image nginx:1.25
# Filter by severity
trivy image --severity HIGH,CRITICAL nginx:1.25
# SARIF output (GitHub Security integration)
trivy image --format sarif --output trivy-results.sarif nginx:1.25
# Secret scan
trivy image --scanners secret myapp:latest
# IaC scan (Dockerfile, Kubernetes YAML)
trivy config .
# Generate SBOM
trivy image --format cyclonedx --output sbom.json nginx:1.25
# .trivyignore - ignore specific CVEs
# Document reason in comments
# CVE-2023-xxxx: Not applicable in our environment (feature not used)
CVE-2023-xxxx
3.3 Grype and syft
# Generate SBOM with syft
syft packages nginx:1.25 -o cyclonedx-json > sbom.json
# Scan SBOM with Grype
grype sbom:./sbom.json
# Direct image scan with Grype
grype nginx:1.25
# Set severity threshold (for CI/CD)
grype nginx:1.25 --fail-on critical
3.4 CI/CD Integrated Scanning
# .github/workflows/image-scan.yml
name: Container Image Scan
on:
push:
branches: [main]
pull_request:
jobs:
build-and-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t myapp:ci .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:ci'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
- name: Run Grype scan
uses: anchore/scan-action@v4
with:
image: 'myapp:ci'
fail-build: true
severity-cutoff: 'high'
4. Image Signing: Sigstore and cosign
4.1 Sigstore Ecosystem
Sigstore Components:
┌──────────────────────────────────────────────────┐
│ cosign │
│ - Sign and verify container images/artifacts │
│ - Keyless signing support (OIDC-based) │
├──────────────────────────────────────────────────┤
│ Rekor │
│ - Immutable transparency log │
│ - All signatures stored publicly │
├──────────────────────────────────────────────────┤
│ Fulcio │
│ - Short-lived certificate issuance (CA) │
│ - Converts OIDC tokens to X.509 certificates │
└──────────────────────────────────────────────────┘
4.2 Signing Images with cosign
# Generate key pair
cosign generate-key-pair
# Sign image
cosign sign --key cosign.key myregistry.com/myapp:v1.0
# Verify image signature
cosign verify --key cosign.pub myregistry.com/myapp:v1.0
# Keyless signing (recommended for CI/CD)
# Auto-authenticates with OIDC token (GitHub Actions, GitLab CI)
cosign sign myregistry.com/myapp:v1.0
# Keyless verification
cosign verify \
--certificate-identity "https://github.com/myorg/myapp/.github/workflows/build.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
myregistry.com/myapp:v1.0
4.3 Keyless Signing in GitHub Actions
# .github/workflows/sign-image.yml
name: Build, Sign, and Push
on:
push:
tags: ['v*']
permissions:
contents: read
packages: write
id-token: write # Required for keyless signing
jobs:
build-sign-push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: sigstore/cosign-installer@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: "${{ github.actor }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
push: true
tags: "ghcr.io/${{ github.repository }}:${{ github.ref_name }}"
- name: Sign the image (keyless)
run: |
cosign sign --yes \
"ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}"
4.4 Kubernetes Admission Controller for Signature Verification
# Kyverno policy: allow only signed images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-cosign-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/myorg/*/.github/workflows/*@refs/heads/main"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: "https://rekor.sigstore.dev"
5. SBOM (Software Bill of Materials)
5.1 SBOM Format Comparison
CycloneDX:
- OWASP project
- Security-focused (vulnerabilities, licenses)
- JSON, XML formats
- VEX (Vulnerability Exploitability eXchange) support
SPDX:
- Linux Foundation project
- License compliance focused
- JSON, RDF, Tag-Value formats
- ISO/IEC 5962:2021 international standard
5.2 Generating SBOM with syft
# Generate SBOM in CycloneDX format
syft packages myapp:latest -o cyclonedx-json > sbom-cyclonedx.json
# Generate SBOM in SPDX format
syft packages myapp:latest -o spdx-json > sbom-spdx.json
# Scan directory
syft dir:./my-project -o cyclonedx-json > project-sbom.json
# Attach SBOM to image (cosign + SBOM)
cosign attach sbom --sbom sbom-cyclonedx.json myregistry.com/myapp:v1.0
# Create SBOM attestation
cosign attest --predicate sbom-cyclonedx.json \
--type cyclonedx \
myregistry.com/myapp:v1.0
5.3 SBOM-Based Vulnerability Management
# Scan vulnerabilities from SBOM
grype sbom:./sbom-cyclonedx.json
# Query specific packages
syft packages myapp:latest | grep log4j
# License analysis
syft packages myapp:latest -o json | \
jq '.artifacts[].licenses[].value' | sort | uniq -c | sort -rn
6. Pod Security Standards
6.1 Security Level Comparison
Privileged:
- No restrictions
- Known privilege escalation allowed
- For system daemons, CNI plugins
Baseline:
- Prevents known privilege escalation
- Blocks hostNetwork, hostPID, hostIPC
- Blocks privileged containers
- Suitable for most workloads
Restricted:
- Least privilege principle applied
- Non-root enforced
- All capabilities dropped
- seccomp profile required
- For security-critical workloads
6.2 Pod Security Admission Configuration
# Apply Pod Security Standards to Namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
# Enforce Restricted level
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
# Warn on Restricted violations
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: latest
# Audit Restricted violations
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: latest
6.3 Security-Hardened Pod Spec
# Pod spec satisfying Restricted level
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
# Security: disable auto-mount of SA token
automountServiceAccountToken: false
securityContext:
# Security: run as non-root group
runAsGroup: 1000
fsGroup: 1000
# Security: apply Seccomp profile
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: ghcr.io/myorg/secure-app:v1.0
ports:
- containerPort: 8080
protocol: TCP
securityContext:
# Security: run as non-root
runAsNonRoot: true
runAsUser: 1000
# Security: read-only root filesystem
readOnlyRootFilesystem: true
# Security: block privilege escalation
allowPrivilegeEscalation: false
# Security: drop all capabilities
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/cache
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: tmp
emptyDir:
sizeLimit: 100Mi
- name: cache
emptyDir:
sizeLimit: 200Mi
7. Network Policies
7.1 Default Deny Policy
# Block all ingress/egress (default deny)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
7.2 Fine-Grained Network Policies
# API service: allow ingress only from specific sources
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-service-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api-service
policyTypes:
- Ingress
- Egress
ingress:
# Allow only from ingress controller
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
podSelector:
matchLabels:
app: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
# Allow database access
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
# Allow DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
7.3 Cilium Network Policy
# Cilium L7 Network Policy (HTTP path-based)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-l7-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-service
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/products"
- method: "POST"
path: "/api/v1/orders"
8. Runtime Security: Falco and Tetragon
8.1 Falco Rules
# Falco custom rules
- rule: Detect Reverse Shell
desc: Detect reverse shell connection attempts in containers
condition: >
evt.type=connect and
evt.dir=< and
container and
fd.typechar=4 and
fd.rip != "127.0.0.1" and
proc.name in (bash, sh, zsh, dash, csh)
output: >
Reverse shell detected (user=%user.name command=%proc.cmdline
connection=%fd.name container=%container.name
image=%container.image.repository)
priority: CRITICAL
tags: [network, shell, mitre_execution]
- rule: Detect Cryptomining
desc: Detect cryptocurrency mining processes in containers
condition: >
spawned_process and
container and
(proc.name in (xmrig, minerd, minergate, cpuminer) or
proc.cmdline contains "stratum+tcp" or
proc.cmdline contains "cryptonight")
output: >
Cryptomining detected (user=%user.name command=%proc.cmdline
container=%container.name image=%container.image.repository)
priority: CRITICAL
tags: [crypto, mining, mitre_resource_hijacking]
- rule: Sensitive File Access
desc: Detect access to sensitive files
condition: >
open_read and
container and
(fd.name startswith /etc/shadow or
fd.name startswith /etc/passwd or
fd.name startswith /proc/self/environ or
fd.name startswith /run/secrets)
output: >
Sensitive file access (user=%user.name file=%fd.name
command=%proc.cmdline container=%container.name)
priority: WARNING
tags: [filesystem, mitre_credential_access]
8.2 Falco Helm Deployment
# Install Falco
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set falcosidekick.enabled=true \
--set falcosidekick.config.slack.webhookurl="https://hooks.slack.com/services/xxx" \
--set falcosidekick.config.slack.minimumpriority=warning \
--set driver.kind=ebpf
8.3 Tetragon eBPF Policies
# Tetragon policy: process execution monitoring
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: monitor-process-execution
spec:
kprobes:
- call: "security_bprm_check"
syscall: false
args:
- index: 0
type: "linux_binprm"
selectors:
- matchBinaries:
- operator: "In"
values:
- "/bin/bash"
- "/bin/sh"
- "/usr/bin/curl"
- "/usr/bin/wget"
matchNamespaces:
- namespace: Mnt
operator: NotIn
values:
- "host_mnt_ns"
---
# Tetragon policy: network connection monitoring
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: monitor-network-connections
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchArgs:
- index: 0
operator: "NotDAddr"
values:
- "127.0.0.1"
- "10.0.0.0/8"
9. Secrets Management
9.1 External Secrets Operator
# SecretStore configuration (AWS Secrets Manager)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secrets
namespace: production
spec:
provider:
aws:
service: SecretsManager
region: ap-northeast-2
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
---
# ExternalSecret definition
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets
kind: SecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: prod/database
property: username
- secretKey: password
remoteRef:
key: prod/database
property: password
9.2 Vault CSI Provider
# Vault SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-db-creds
namespace: production
spec:
provider: vault
parameters:
vaultAddress: "https://vault.example.com"
roleName: "app-role"
objects: |
- objectName: "db-username"
secretPath: "secret/data/prod/database"
secretKey: "username"
- objectName: "db-password"
secretPath: "secret/data/prod/database"
secretKey: "password"
---
# Using in Pod
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
serviceAccountName: app-sa
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: secrets
mountPath: "/mnt/secrets"
readOnly: true
volumes:
- name: secrets
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: vault-db-creds
10. SLSA Framework
10.1 SLSA Levels
SLSA Level 1 - Provenance:
- Build process documented
- Automated build
SLSA Level 2 - Build Service:
- Hosted build service
- Signed provenance generated
- Version-controlled source
SLSA Level 3 - Build Integrity:
- Isolated build environment
- Tamper-resistant provenance
- Source integrity guaranteed
SLSA Level 4 - Dependencies:
- Recursive assurance for all dependencies
- Reproducible builds
- (Currently theoretical)
10.2 Generating SLSA Provenance
# SLSA Provenance generation in GitHub Actions
name: SLSA Build
on:
push:
tags: ['v*']
permissions:
contents: read
packages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
outputs:
digest: "${{ steps.build.outputs.digest }}"
steps:
- uses: actions/checkout@v4
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
push: true
tags: "ghcr.io/${{ github.repository }}:${{ github.ref_name }}"
provenance:
needs: build
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
with:
image: "ghcr.io/${{ github.repository }}"
digest: "${{ needs.build.outputs.digest }}"
secrets:
registry-username: "${{ github.actor }}"
registry-password: "${{ secrets.GITHUB_TOKEN }}"
11. CI/CD Security Pipeline
11.1 Complete Pipeline Architecture
Security CI/CD Pipeline:
┌─────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│Build│ -> │ Scan │ -> │ Sign │ -> │Attest│ -> │Verify│ -> │Deploy│
└─────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
| | | | | |
Build Vuln cosign SBOM Kyverno Signature
image scan signing attestation policy verified
Trivy SLSA check deploy
Grype provenance
11.2 CIS Benchmarks and Kubescape
# kube-bench: run CIS Kubernetes Benchmark
kube-bench run --targets master,node
# Kubescape: NSA, MITRE, CIS framework scan
kubescape scan framework cis-v1.23 --exclude-namespaces kube-system
# Scan specific control
kubescape scan control C-0002 --namespace production
# Kubescape YAML scan
kubescape scan .
12. Quiz
Test your understanding of container security covered in this article.
Q1. Image Security
Question: What is the difference between Distroless images and Alpine images?
Answer: Distroless images are minimal images without a shell (bash/sh) or package manager. Alpine is a lightweight Linux distribution based on musl libc that includes a shell and package manager (apk).
Distroless has a smaller attack surface but is harder to debug. Alpine allows debugging but may have musl libc compatibility issues. For production, Distroless or Chainguard images are recommended, using debug-tagged variants when debugging is needed.
Q2. Sigstore Keyless Signing
Question: Why is cosign keyless signing preferred over key-based signing in CI/CD?
Answer: Keyless signing uses OIDC tokens (e.g., GitHub Actions workflow ID tokens), eliminating the need to manage and protect long-lived private keys.
Fulcio converts OIDC tokens to short-lived certificates, and signatures are recorded in the Rekor transparency log. This eliminates key rotation, key leakage, and key storage concerns, significantly reducing operational burden in CI/CD environments.
Q3. Pod Security Standards
Question: List three security requirements that must be met at the Restricted level of Pod Security Standards.
Answer:
- Run as non-root user (runAsNonRoot: true)
- Drop all Linux capabilities (capabilities.drop: ALL)
- Block privilege escalation (allowPrivilegeEscalation: false)
Additionally, applying a seccomp profile (RuntimeDefault or Localhost) and read-only root filesystem (readOnlyRootFilesystem: true) are also recommended at the Restricted level.
Q4. Runtime Security
Question: Explain the architectural differences between Falco and Tetragon.
Answer:
- Falco: Captures system calls via a kernel module or eBPF driver, analyzing events in a userspace rules engine. Detection-focused, generating alerts when rules match.
- Tetragon: Pure eBPF-based, executing policies directly at the kernel level. Supports both detection and enforcement, directly controlling process execution, network connections, and file access at the kernel level.
Q5. SLSA Framework
Question: What are the two core security properties required at SLSA Level 3?
Answer:
- Isolated build environment: Builds run in an environment isolated from other builds, preventing cross-contamination.
- Tamper-resistant provenance: The provenance generated by the build system cannot be modified by the build itself. Provenance is signed by the build service, ensuring the integrity of both source and build process.
13. References
- Trivy - https://aquasecurity.github.io/trivy/
- Sigstore (cosign, Rekor, Fulcio) - https://www.sigstore.dev/
- SLSA Framework - https://slsa.dev/
- Falco - https://falco.org/docs/
- Tetragon - https://tetragon.io/docs/
- Grype - https://github.com/anchore/grype
- syft - https://github.com/anchore/syft
- CycloneDX - https://cyclonedx.org/
- SPDX - https://spdx.dev/
- Kyverno - https://kyverno.io/docs/
- External Secrets Operator - https://external-secrets.io/
- Kubescape - https://kubescape.io/
- Chainguard Images - https://www.chainguard.dev/chainguard-images
- CIS Benchmarks - https://www.cisecurity.org/benchmark/kubernetes
This article covered the entire lifecycle of container security: image security (minimal base images, scanning), signing and verification (Sigstore/cosign), SBOM, Pod Security Standards, Network Policies, runtime security (Falco/Tetragon), secrets management, the SLSA framework, and CI/CD security pipelines. Adopting a Defense in Depth strategy and integrating security from development through CI/CD pipelines is key.