If you ship software today, you don’t just ship your code.
You ship:
- open-source libraries
- base container images
- build tools and plugins
- CI runners
- package registries
- container registries
- deployment pipelines
- and a long chain of “stuff” you didn’t write
That whole chain is your software supply chain.
And attackers love it, because instead of hacking your production server directly, they can:
- slip something into a dependency,
- poison a build,
- steal a CI token,
- publish a malicious package version,
- or replace an artifact in the registry.
Supply chain security is how you make that harder—without slowing engineering to a crawl.
This guide explains the key ideas in plain English:
- SBOM: “What’s inside this software?”
- SLSA: “How trustworthy was the build process?”
- Signing: “Did this artifact really come from us?”
- Provenance: “Show me exactly how this was built.”
Then we’ll build a practical, step-by-step implementation you can apply to containers, libraries, and deployments.
The 60-second picture
Imagine you’re buying medicine.
You want:
- Ingredients list (SBOM)
- Factory quality rating (SLSA)
- Tamper-proof seal (Signing)
- Production record (Provenance)
Software is the same. We want proof, not promises.
1) SBOM: Software Bill of Materials (ingredients list)
What SBOM means (simple)
An SBOM is a structured list of everything your software contains:
- direct dependencies (what you chose)
- transitive dependencies (what your dependencies chose)
- versions
- hashes
- licenses (optional but useful)
Think: “npm list” / “pip freeze” but standardized and machine-readable.
Why SBOM matters (real reasons engineers care)
SBOM lets you answer these questions fast:
- “Are we affected by CVE-XYZ?” (yes/no in minutes)
- “Where is log4j used?” (exactly which services/images)
- “Do we ship GPL code accidentally?” (license visibility)
- “Which teams use this vulnerable library?” (ownership + blast radius)
Without SBOM, vulnerability response becomes a company-wide panic and guessing game.
SBOM formats you’ll hear about
Two common SBOM standards:
- SPDX
- CycloneDX
Pick one. Don’t get stuck debating. The best SBOM is the one you generate consistently.
SBOM pitfalls (what goes wrong)
- SBOM generated once and forgotten (becomes outdated)
- SBOM exists but not stored with the artifact (can’t find it later)
- SBOM created, but no process to use it for decisions
Rule: Generate SBOM for every build, store it next to the artifact, and make it searchable.
2) SLSA: Supply-chain Levels for Software Artifacts (how trustworthy was the build?)
What SLSA is (simple)
SLSA (pronounced “salsa”) is a framework that describes how secure your build process is, in levels.
It’s not a tool. It’s a maturity ladder.
SLSA asks:
- Can someone tamper with the build?
- Are builds repeatable?
- Is provenance produced and protected?
- Are dependencies controlled?
The practical view of SLSA levels
You’ll often see levels from 1 to 4:
- SLSA 1: You produce some build info (basic provenance)
- SLSA 2: Builds run in a controlled system (CI), provenance is generated
- SLSA 3: Builds are hardened (isolated, tamper-resistant), provenance is stronger
- SLSA 4: Highest assurance (strict, often hard to reach for many orgs)
Where most teams should aim first
For most engineering teams, the realistic target is:
- Start with SLSA 2 quickly
- Move toward SLSA 3 for critical services
Trying to jump to “perfect” usually means you do nothing for 6 months.
3) Signing: “This artifact is really ours” (tamper-proof seal)
What signing means (simple)
Signing adds a cryptographic “seal” to an artifact (container image, binary, package).
If anyone modifies the artifact after signing, verification fails.
Signing answers:
- “Did this come from our build pipeline?”
- “Has it been tampered with in the registry?”
- “Can we block unsigned artifacts in production?”
What you can sign
Common items to sign:
- container images
- binaries
- packages (npm, maven, python wheels)
- SBOM files
- provenance files
- Helm charts
- manifests
Best practice: Sign the artifact and also sign/attach the SBOM + provenance.
Keys: the scary part (made simple)
You have two broad approaches:
A) Key-based signing (traditional)
- You store private keys somewhere (HSM, vault, KMS)
- CI uses them to sign
Pros: familiar
Cons: key management can be painful; keys can be stolen
B) Keyless signing (modern, CI identity-based)
- No long-lived private key sitting around
- CI proves identity using OIDC-like short-lived identity tokens
- Signatures tie to “this CI job in this repo at this commit”
Pros: reduces key theft risk
Cons: requires a clean CI identity model and good verification rules
Either is fine. Choose what your team can operate safely.
4) Provenance: “Show me how this was built” (production record)
What provenance means (simple)
Provenance is a verifiable record of the build:
- source repo and commit
- build system identity (which CI, which workflow)
- build steps / builder
- dependencies used (sometimes)
- timestamps
- output artifact digest (hash)
Provenance answers:
- “Was this built from the commit we reviewed?”
- “Was it built by our official pipeline or someone’s laptop?”
- “Which build job produced this artifact?”
Provenance is most powerful when…
- it’s generated automatically by CI
- it’s signed
- it’s stored with the artifact
- your deploy system verifies it before running
Otherwise, it’s just a PDF nobody reads.
How these pieces fit together (one clean flow)
| Concept | Simple question it answers | What it protects against |
|---|---|---|
| SBOM | “What’s inside?” | Unknown vulnerable deps, slow incident response |
| Signing | “Is it authentic and unchanged?” | Registry tampering, artifact swapping |
| Provenance | “How exactly was it built?” | Untrusted builds, rogue pipelines, hidden steps |
| SLSA | “How strong is our build chain?” | Systemic supply-chain weakness |
If you implement only one thing first: sign + verify at deploy time.
If you implement two: sign + provenance.
If you implement three: sign + provenance + SBOM (now you can respond fast to CVEs).
SLSA becomes the maturity scoreboard tying it all together.
Step-by-step: a practical secure supply chain you can implement
You can apply this to containers first (fastest ROI), then expand to libraries and binaries.
Step 0 — Pick one “golden path” target
Start with one service and one artifact type:
- “All container images for
payments-api” - “All Helm charts for platform services”
- “All Java jars in this repo”
Small scope, real rollout.
Step 1 — Lock down your source inputs (stop “dependency drift”)
Supply chain attacks often enter through “moving targets.”
Do these first:
- Pin dependency versions (no floating
latest) - Lockfiles committed (package-lock, poetry.lock, go.sum, etc.)
- Pin base images by digest (not just
ubuntu:22.04) - Pin CI actions/plugins by version or digest
- Restrict who can change CI workflows (code owners)
Real example
Bad:
FROM node:latestuses: some/action@main
Better:
FROM node@sha256:<digest>uses: some/action@v3
This alone blocks a huge class of “upstream changed silently” problems.
Step 2 — Make builds reproducible and isolated (stop “works on my laptop builds”)
Aim for:
- builds run only in CI (not local manual builds to prod)
- ephemeral runners (fresh VM/container per build)
- minimal secrets exposure (no broad cloud keys in CI)
- clean build steps with least privilege
Practical controls engineers can implement quickly
- Use short-lived credentials (assume-role style patterns)
- Separate “build” and “deploy” permissions
- No production secrets accessible from build jobs
- Store artifacts in a controlled registry with write restrictions
Step 3 — Generate SBOM automatically (every build)
You want SBOM generation to be:
- automatic
- repeatable
- stored with the artifact
- queryable later
What “good” looks like
When you build myapp:1.2.3, you also produce:
myapp:1.2.3(the image)myapp:1.2.3.sbom.json(SBOM)- both stored and tied together by digest
Even better: attach SBOM as artifact metadata in your registry system (if supported).
Step 4 — Sign artifacts (and attach signatures)
Signing should happen after build and before publish/deploy.
Minimum viable signing:
- sign container images in CI right after pushing to registry
Better:
- sign image + sign SBOM + sign provenance
Real example policy you want to enforce later
“Only run images that are signed by our CI identity.”
That means:
- random images cannot be pulled and deployed
- tampered images fail verification
Step 5 — Generate provenance (build proof)
Provenance should include:
- repo URL (or identifier), commit SHA
- CI workflow identity
- builder version
- artifact digest
Then it should be:
- signed
- stored with the artifact
Engineers love provenance because it answers “what produced this?” instantly.
Step 6 — Verify at the gate (this is where security becomes real)
If you only generate SBOM/signatures/provenance but never enforce verification, attackers can still slip things in.
So you add verification at:
A) CI promotion gates
Example:
- “Promotion to prod requires signed artifact + provenance present.”
B) Kubernetes admission control (strong)
Example:
- Block deployment unless image is signed by your org
- Optionally require provenance with minimum SLSA level
C) Runtime policy (when applicable)
Example:
- Allow only approved registries
- Disallow
latesttags - Disallow privileged pods for non-platform namespaces
This is the moment supply chain security stops being documentation and becomes protection.
Step 7 — Make it operational (otherwise it dies)
Add routines:
- Weekly: top unsigned attempts blocked, top policy violations
- Monthly: SBOM coverage %, provenance coverage %, top vulnerable deps
- Quarterly: move one tier up in SLSA maturity for critical services
Track a few simple KPIs:
- % artifacts signed
- % artifacts with provenance
- % builds generating SBOM
- mean time to answer “are we affected by CVE-X?”
Real-world examples (plain scenarios)
Example 1: “Registry artifact swap”
Attack: someone with registry access replaces myapp:1.2.3 with a backdoored image.
Without signing: Kubernetes pulls it happily.
With signing + verification: verification fails → deploy blocked.
Example 2: “Compromised CI token”
Attack: attacker steals CI token and pushes a malicious image.
Protection chain:
- Restrict who can run release workflows
- Require provenance that matches official workflow identity
- Verify signature + provenance at deploy
- Use short-lived credentials and minimal scope tokens
Now even if something gets pushed, it won’t meet verification requirements.
Example 3: “Critical CVE response”
Situation: a high severity vulnerability drops. Leadership asks: “Are we impacted?”
Without SBOM: 2 days of grep + panic.
With SBOM: query SBOM index → list affected services/images in minutes.
Then you prioritize upgrades based on:
- exposure (internet-facing?)
- exploitability
- runtime usage
A “starter blueprint” you can copy (small but strong)
If you want a practical first milestone, do this:
Week 1–2: Minimum viable protection
- Pin dependencies and base images
- Generate SBOM for each build
- Sign container images in CI
Week 3–4: Add real enforcement
- Verify signatures in CD or at Kubernetes admission
- Block unsigned images in prod
Month 2: Add provenance + maturity
- Generate signed provenance for builds
- Require provenance for critical namespaces/services
Month 3+: Expand coverage
- Sign and verify Helm charts/manifests
- Add policies for “no latest”, “approved registries only”
- Improve SLSA maturity for top 10 services by spend/criticality
Common mistakes (and how to avoid them)
Mistake 1: “We’ll secure everything at once”
Fix: start with one artifact type (containers) + one team.
Mistake 2: “We generated SBOM, done”
Fix: SBOM is only useful when searchable and used during incidents.
Mistake 3: “We sign, but we don’t verify”
Fix: verification is the enforcement point. Without it, signing is decoration.
Mistake 4: “We rely on long-lived keys in CI without guardrails”
Fix: minimize key exposure, rotate, and prefer short-lived identity when possible.
Mistake 5: “Policies block everything and teams revolt”
Fix: start with warn mode, measure violations, then gradually enforce in prod.
A short FAQ (quick answers)
Do beginners really need this?
Yes—because supply chain attacks don’t care if you’re “small.” They target the easiest path in.
Is this only for containers?
No. It applies to packages, binaries, scripts, infrastructure modules—anything you ship or deploy.
Does this slow delivery?
Not if you build a golden path and automate it. The goal is secure-by-default pipelines.
What should I implement first?
Signing + verification for production deployments. It gives immediate control.
Final takeaway (the line to remember)
SBOM tells you what’s inside.
Signing proves it’s yours.
Provenance proves how it was made.
SLSA tells you how trustworthy the whole process is.