Your release includes more than your source
A production artifact contains application code, direct dependencies, transitive dependencies, build tools, base images, generated files, and configuration. An attacker can target any part of that chain. A package may be compromised upstream, a maintainer account may be hijacked, or a build runner may fetch a different artifact than the developer tested. Supply-chain security starts by naming what enters the release and who can change it.
Do not treat a vulnerability scanner as the whole program. A scanner can find known versions and suspicious patterns, but it cannot prove that a dependency is trustworthy or that the build used the intended source. Combine dependency inventory, provenance, review, least privilege, runtime controls, and a practiced incident response.
Make dependency resolution reproducible
Commit lockfiles and use a package manager mode that honors them in CI. Pin or constrain base images and tool versions, and record the digest of the final image. A semver range can resolve to a new package on a later build even when the source did not change. Reproducibility does not mean freezing forever; it means a change is intentional, reviewable, and recoverable.
Use a private or verified registry path where appropriate, and protect publish credentials separately from install credentials. Do not let a build fetch arbitrary packages from a URL derived from a pull request. Validate package names, integrity checksums, and registry configuration. A convenient install script that executes remote shell code is a high-risk dependency boundary.
Separate build and runtime permissions
A build step may need to compile assets, but it should not automatically have production database credentials or the ability to deploy every service. Use short-lived identities and separate roles for source retrieval, artifact publishing, deployment, and runtime. A compromised dependency in the build should not be able to read a production secret merely because the build environment can see it.
Use multi-stage containers to keep compilers and package caches out of the runtime image. Generate an artifact summary with source revision, dependency lockfile hash, base image digest, and build identity. Do not include secrets in the summary. The runtime service should be able to prove which artifact it runs without having to reproduce the build in production.
Review scripts and transitive behavior
Package installation scripts can execute with the permissions of the build. Review lifecycle hooks, native modules, post-install downloads, and code generation. A dependency with few source lines can pull in a large transitive tree. Keep production dependencies separate from development tools when possible, and fail the build when an unexpected package or registry appears.
Use allowlists and exception ownership for packages with native code, network access, or broad filesystem needs. Do not blindly remove a package because a scanner flags it; identify whether it is reachable, exploitable, and patchable. Conversely, do not dismiss a high-severity issue because the vulnerable code is not currently exercised without documenting why.
Publish provenance and verify artifacts
Artifact provenance links a built image or package to source, builder, inputs, and time. Store it in a system operators and deployers can query. Verify the image digest during deployment and prevent mutable tags from silently changing after approval. A signed artifact is useful only when the deployment environment verifies the signature and trusts the correct identity.
Keep promotion separate from rebuilding. Build once, scan and attest the artifact, then promote the same digest through environments. Rebuilding from the same commit can still produce different dependencies or base layers. A promotion record should include the approver, policy checks, image digest, and rollback target.
Prepare for a compromised dependency
A response plan should identify how to freeze promotion, revoke registry credentials, find affected artifacts, rotate secrets that the build could read, and communicate with users. Dependency compromise is not only a code patch. A malicious package may have exfiltrated environment variables or modified generated output. Preserve logs and build metadata before deleting artifacts or caches.
Use a narrow emergency path that can rebuild from a known-good registry and lockfile. Keep a list of high-impact dependencies and owners so investigation does not start with a blank page. Test the path in a tabletop exercise. The team should know who can quarantine an artifact and who can approve a replacement.
Measure the chain over time
Track dependency age, unsupported packages, high-severity findings, lockfile drift, base image age, provenance coverage, build identity changes, and time to patch. Alert on a release that lacks an expected attestation or introduces an unreviewed registry. Do not turn every low-risk warning into a page; route routine maintenance to an owner with a deadline.
Supply-chain security is a delivery discipline. Reproduce inputs, separate permissions, review behavior, attest artifacts, and rehearse compromise recovery. These controls let a small team move quickly because the release path provides evidence instead of relying on trust in every package and build runner.
A release review checklist
Before approving a release, confirm the source revision, lockfile hash, base image digest, builder identity, scan result, and deployment digest. Verify that no production secret was available to an untrusted build step and that the runtime identity cannot publish or modify artifacts. Keep the previous digest available for rollback and record who owns the exception if a finding remains open.
After deployment, compare the running artifact with the approved digest and review provenance in the same system an operator uses during an incident. Recheck high-impact dependencies on a schedule, not only when a scanner reports a new CVE. The supply chain is healthy when the team can answer what entered the image, who approved it, and how to replace it without improvising.
Keep the inventory useful to incident responders: include package coordinates, versions, image layers, build jobs, and the services that consume the artifact. When a compromised release is discovered, the responder should be able to query affected revisions and owners in minutes. Evidence that is technically complete but operationally hard to search is not enough during a fast-moving supply-chain event.
Connect provenance to deployment policy
A provenance statement is most useful when the deploy step verifies it before accepting an artifact. Require the expected repository, commit, builder, and dependency policy, then record the digest that passed. Keep a quarantine path for unverified images and a documented exception owner. This makes supply-chain controls enforceable at the boundary where an artifact becomes executable, rather than leaving scan results as advisory files no operator checks.
Implementation example
Generate a software bill of materials and provenance statement in a trusted build, sign the image or artifact, scan it, and verify repository, commit, builder, and policy before deployment. Keep the approved digest and rollback digest in the release record. Do not make untrusted pull-request code a credentialed build step.
cosign verify --certificate-identity-regexp '.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com IMAGE@DIGESTVerify and troubleshoot
Test a clean build, tampered artifact, unexpected builder, vulnerable dependency, revoked signing key, and missing provenance. Confirm the deploy gate rejects unverified images and that scan exceptions include owner, reason, expiry, and compensating control. Trace one runtime binary back to source revision, dependency lockfile, build job, and deployed digest.
Operations and recovery
Maintain inventories of packages, image layers, builders, service consumers, and owners. Monitor new advisories and unexpected artifact changes, keep a quarantine path, and practice rollback to a verified digest. If compromise is suspected, stop promotion, revoke signing material, identify affected revisions, and rebuild from a trusted source rather than editing the image in place.
References and further reading
Use SLSA, SPDX or CycloneDX SBOM guidance, Sigstore documentation, and NIST SSDF. Define the minimum provenance and vulnerability policy required before an artifact can run in production.