Back to Cheat Sheets

🔗 Supply Chain Vulnerabilities

OWASP Kubernetes Top 10 - K02

HIGH RISK

📋 What Is It?

Supply Chain Vulnerabilities are the risks that enter a cluster through the artifacts it runs - base images, third-party dependencies, build pipelines, registries, Helm charts, and operators - rather than through the cluster's own configuration. The core question is one of provenance: can you prove that what is running is exactly what you intended, built from sources you trust, and free of known-vulnerable components? For most clusters images are pulled by mutable tag, unsigned, and unscanned - and Kubernetes will faithfully schedule whatever it is handed.

K02 OWASP Rank
Provenance Focus Area
Hard To Prevent

⚠️ Common Exploits

  • Poisoned Image: Layers carry attacker code that runs on every replica and reschedule (miner, reverse shell, harvester)
  • Mutable Tag Swap: :latest is repushed to a tampered digest; the next kubelet pull silently runs it
  • Typosquatted Image: A look-alike name (library-nginx vs library/nginx) is pulled as if trusted
  • Stale Base CVE: A legitimate but unpatched image is fingerprinted and hit with a catalogued exploit
  • Pipeline Compromise: A leaked token or poisoned CI action injects an implant into "the official build" (SolarWinds-class)
  • Dependency Confusion: A malicious public package substitutes for an internal one during the build
  • Embedded Secrets: Credentials baked into layers are extracted with docker history - permanently

🔴 Attack Flow

1. Position: publish/poison a malicious artifact
↓
2. Get pulled: a manifest references it by tag
↓
3. Execute: container content runs inside a Pod
↓
4. Escalate: read secrets & service-account token
↓
5. IMPACT: Fleet-wide code execution, no app bug!

❌ Vulnerable Code

# Bad: mutable base, root, secrets baked in FROM ubuntu:latest RUN apt-get update && apt-get install -y python3 curl build-essential COPY . /app COPY .env /app/.env # secrets baked into a layer (permanent) ENV API_TOKEN=sk_live_abc123 # visible in image history forever WORKDIR /app # No USER -> container runs as root (UID 0) CMD ["python3", "server.py"] # Bad: manifest pulls by mutable tag spec: containers: - name: app image: myapp:latest # resolves to a new digest over time imagePullPolicy: Always # does NOT make :latest immutable # Bad: CI builds and pushes with no scan, SBOM, or signature steps: - run: docker build -t registry.example.com/app:latest . - run: docker push registry.example.com/app:latest # Whatever built is trusted implicitly. No admission control blocks it.

✅ Secure Code

# Good: multi-stage, digest-pinned distroless, non-root, no secrets FROM python:3.12-slim@sha256:<digest> AS build WORKDIR /src COPY requirements.txt . RUN pip install --no-cache-dir --require-hashes -r requirements.txt --target /install COPY . . FROM gcr.io/distroless/python3-debian12@sha256:<digest> # no shell, no pkg mgr WORKDIR /app COPY --from=build /install /usr/lib/python3/dist-packages COPY --from=build /src/server.py /app/server.py USER 10001 # non-root; secrets injected at runtime ENTRYPOINT ["python3", "server.py"] # Good: manifest pins the exact artifact by immutable digest image: registry.example.com/app@sha256:9f2c...e1a7 # Good: CI scans, builds an SBOM, signs, and attests provenance steps: - run: trivy image --exit-code 1 --severity HIGH,CRITICAL "$IMG" # CVE gate - run: syft "$IMG" -o cyclonedx-json > sbom.json # SBOM - run: cosign sign "$IMG" # keyless signature - run: cosign attest --predicate provenance.json --type slsaprovenance "$IMG"

✓ Prevention Checklist

  • Start from minimal, trusted base images (distroless/slim); rebuild regularly
  • Pin every image by immutable digest (@sha256:...), never a mutable tag
  • Scan for CVEs in CI (Trivy/Grype) and re-check at admission
  • Sign images with cosign and verify signatures before running
  • Attach SLSA / in-toto provenance attestations
  • Generate and store an SBOM (Syft, CycloneDX/SPDX) for each image
  • Allow-list trusted registries; mirror upstreams internally
  • Enforce policy at admission - block unsigned, unscanned, mutable-tag images
  • Vet and version-pin Helm charts and operators; review their RBAC
  • Keep secrets out of layers; inject at runtime; scan with gitleaks
  • Run as non-root with a read-only root filesystem by default

🔍 Detection & Tools

Scan, Sign & SBOM:

Trivy Grype Syft Cosign / Sigstore gitleaks kubescape

Admission Enforcement:

Kyverno OPA/Gatekeeper Connaisseur

How to Test:

  • Verify signature: cosign verify registry.example.com/app@sha256:...
  • Re-scan the exact digest: trivy image --severity HIGH,CRITICAL <digest>
  • Inspect layers for secrets: docker history --no-trunc / dive
  • Audit manifests for mutable tags (any image: *:latest)
  • Verify a Helm chart before install: helm pull ... --verify

🌍 Real-World

  • Malicious crypto-miner images on public registries: Researchers have repeatedly documented public images with plausible names that silently run cryptocurrency miners on victims' infrastructure - implicit trust in public-registry images with no provenance verification.
  • Dependency confusion / substitution: A documented class where a build resolves an internal package name from a public index the attacker published to, baking malicious code into images that ship to production.
  • Build-pipeline compromise (SolarWinds-class): The pipeline itself is compromised, so malicious code is inserted into an otherwise legitimate, signed-off artifact that downstream consumers deploy as trusted software.
  • Note: These are described as classes of publicly documented events. Exact figures vary by source and year; the durable takeaway is that most clusters cannot currently prove what they run or what is inside it.

📌 Quick Tips

  • DO NOT pull by mutable tag like :latest
  • DO NOT trust an image just because it's on Docker Hub
  • DO NOT bake secrets into image layers
  • DO pin by digest and verify signatures
  • DO scan in CI and at admission
  • DO generate and store an SBOM
  • DO vet charts and operators before install

📜 Compliance

Related Standards:

  • SLSA Supply-chain Levels for Software Artifacts
  • NIST SSDF (800-218) Secure Software Development
  • CIS Software Supply Chain Security Guide
  • Executive Order 14028 SBOM requirements
  • in-toto Attestation framework