Delivery and supply chain · For Platform engineers, security architects, open-source maintainers
Supply-chain boundaries: what you build on is part of your system
Dependencies, base images and CI actions run with your privileges but are written by other owners. How to control what enters, know what you shipped, prove how it was built, and be a good upstream.
4 min read9 sources
Most of the code you run in production was written by people you have never met. Your architecture should say where that trust begins and ends.
What you build on is part of your system
A modern service is mostly other people's code: hundreds of open-source packages, a base image, language runtimes, build tools, CI actions, and SDKs for every vendor it talks to. Each of them runs with your service's privileges. Each was written and published by an owner you do not control. In trust boundary terms, every one is an administrative-domain boundary that your code crosses at build time and keeps crossing at runtime.
Supply-chain attacks exploit exactly that: a maintainer's account taken over, a malicious version published to a public registry, a package name chosen to be confused with an internal one, a build system altered to inject code that never appears in the source. The defences are architectural. They decide where third-party code enters, what is allowed through, and what evidence travels with the result.
Draw the supply chain as boundaries
Draw the paths by which other people's code reaches production, the same way you would draw a request path.
Read the diagram as text
- Other owners: Package maintainers, Image and action authors
- Your intake: Registry proxy, Digest pins
- Your build and runtime: Build job, Signed artifact, Production
- Package maintainers → Registry proxy: pull through
- Image and action authors → Digest pins: pin
- Registry proxy → Build job: resolve
- Digest pins → Build job: base image
- Build job → Signed artifact: attest
- Signed artifact → Production: same digest
Control what enters
The intake column is where most supply-chain risk can be cut cheaply.
- Resolve through a registry you control. A proxy or mirror in front of public registries gives you one place to record what was fetched, block known-bad versions and keep builds working when upstream disappears.
- Lock everything. Lock files for packages, digests for base images, commit hashes for CI actions. A mutable tag is an invitation for someone else to change your build.
- Reserve your internal names. Dependency confusion works when a build that expects an internal package can be satisfied by a public one with the same name. Scope internal packages to a namespace you own and configure resolvers to fetch them only from your registry.
- Treat install-time scripts as code execution. Disable them where the ecosystem allows, and run builds without credentials that matter, as in our guide to securing CI/CD.
- Update deliberately. Automated update proposals on a regular cadence, reviewed like any other change, beat both "never update" and "always take the latest the moment it appears".
- Hold coding agents to the same intake. Agents that write code also choose packages and edit build files. Write the rules down where they read them: approved registries, lock files only, and no new dependency without review.
Know what you shipped
When the next widely used library turns out to be vulnerable, the first question is where it runs. A software bill of materials generated for every built artifact, in a standard format such as SPDX or CycloneDX and stored against the artifact's digest, answers it in minutes. Pair SBOMs with vulnerability exploitability statements where you have established that a product is not affected, so the answer includes "and why we are not exposed".
Then use that inventory as described in from vulnerability to architectural impact: presence is the first question, not the last.
Prove how it was built
An SBOM says what is inside an artifact; provenance says where it came from. Build provenance records the source revision, the build definition and the builder that produced an artifact. The SLSA framework describes levels of assurance for that record, from provenance that simply exists to provenance generated by a hardened build platform that the build itself cannot forge.
Sign artifacts and their attestations, using keyless signing tied to the build's identity where you can, and verify signatures and provenance at deployment. Verification is the step teams most often skip, and without it signing changes nothing.
Be a good upstream
Every organisation that publishes code, an SDK, a library, a container image, is part of someone else's supply chain. The same practices apply in reverse:
- Publish a
SECURITY.mdthat explains how to report a vulnerability and what reporters can expect. - Require strong multi-factor authentication for everyone who can publish releases.
- Sign releases and publish provenance, so your users can verify what they install.
- Issue advisories when you fix vulnerabilities, so downstream teams can act.
Plan for the attacks your controls will miss
Intake controls stop the common cases: typosquatted names, confused internal packages, a known-malicious version. Two kinds of attack get past them, and your architecture should assume they will.
A trusted upstream turns hostile. In 2024 a backdoor was found in releases of the xz compression utilities, inserted by a contributor who had spent years earning maintainer trust. Pinning and proxies do not help when the legitimate release is the malicious one. What helps is containment: services that run with narrow identities, little outbound network access and no more privilege than their job needs, so that a compromised library inherits a small blast radius. See failure containment.
The build itself is compromised. When attackers alter a build system, the source code stays clean and the shipped artifact does not. Reviewing source cannot catch this. Isolated, ephemeral build environments, provenance generated by the build platform rather than the build script, and reproducible builds where you can afford them are the controls that do.
In both cases, the SBOM and provenance you recorded earlier become the incident response tools: they tell you which artifacts contain the affected component, where they run, and which builds produced them.
A short checklist
- A drawing of every way third-party code enters your builds and runtime.
- All packages resolved through a registry you control, from lock files.
- Base images and CI actions pinned by digest or commit.
- Internal package names reserved and resolved only internally.
- An SBOM per artifact, stored against its digest.
- Signed provenance, verified before deployment.
- A published vulnerability disclosure policy for every repository you release.
Sources
- SLSA specification v1.0
OpenSSF
- Cybersecurity Supply Chain Risk Management Practices (SP 800-161 Rev. 1)
NIST
- Secure Software Development Framework (SP 800-218)
NIST
- Software Bill of Materials (SBOM)
CISA
- CycloneDX specification
OWASP CycloneDX
- SPDX specification
The Linux Foundation
- Sigstore documentation
Sigstore
- Vulnerable Dependency Management Cheat Sheet
OWASP
- Reported supply chain compromise affecting XZ Utils (CVE-2024-3094)
CISA