# Software Supply Chain Security: Dependencies, Builds, and Releases

> Secure the software supply chain from dependency selection through release — lockfiles, provenance, least privilege, secret controls, SBOMs, and response.

Software supply-chain security protects the path from source and dependencies through CI, artifacts, and deployment. A practical program minimizes dependency trust, reviews resolution, isolates builds, limits automation credentials, verifies provenance, inventories shipped components, and prepares fast revocation and rebuild procedures for upstream compromise.

**Software supply-chain security protects everything that can influence a shipped artifact.** The attack surface includes source repositories, third-party packages, registries, CI actions, build images, compiler and package-manager plugins, signing keys, artifact stores, deployment credentials, and increasingly the skills and tools installed into coding agents.

The defining challenge is transitive trust. Your application may contain hundreds of packages maintained by people you never selected directly, built by infrastructure configured in reusable workflows, and published through credentials available to automation. One compromised upstream account or mutable build reference can reach every downstream user.

The goal is not to eliminate external code. It is to make trust explicit, narrow, reproducible, observable, and revocable.

## Map the release trust graph

Start from the production artifact and work backward:

- Which source repository and branch can produce it?
- Which people, bots, and apps can merge or tag a release?
- Which CI workflows and reusable actions execute?
- Which base images, build tools, plugins, and package registries supply code?
- Which secrets and identity tokens are available to each job?
- Where are artifacts stored, signed, promoted, and deployed?
- Can a deployment verify what source and build produced the artifact?

Mark the components whose compromise can alter a release. Those are trust roots even if they look like development conveniences.

Include AI-agent extensions. A skill can contain scripts, an MCP server can execute with credentials, and an agent can install dependencies or modify workflows. Markdown instructions are less privileged than a compiler only when the environment ensures they cannot trigger privileged tools.

## Govern dependency intake

Before adding a package, evaluate:

- Does the project need it, or can the platform or an existing dependency solve the job?
- Who owns it, and how many maintainers can publish?
- Is maintenance active and release history understandable?
- What is the dependency and install-script footprint?
- Does the license fit distribution and business use?
- Does it require native code, network access, or privileged setup?
- Is there a credible exit path if maintenance stops?

A tiny utility can carry a large transitive tree. Review the resolved graph, not only the top-level package description.

Use organization-approved registries or mirrors where appropriate, reserve internal package names, and protect against namespace confusion. For private packages, configure explicit scopes so the package manager cannot silently resolve the name from a public registry.

## Make resolution reproducible and reviewable

Commit the ecosystem's lockfile and update it through controlled tooling. A dependency pull request should show:

- manifest range changes
- exact resolved-version changes
- added and removed transitive packages
- integrity or checksum changes
- new install or build scripts
- vulnerability and license results
- test and build evidence

Do not hide a large lockfile rewrite beside unrelated application changes. Review tools should distinguish ordinary metadata churn from new packages, changed sources, and executable scripts.

Lockfiles do not establish safety. They establish repeatability: reviewers and CI can see and reproduce the exact dependency graph. A malicious version remains malicious when pinned.

Disable package lifecycle scripts by default in high-risk or untrusted builds when the ecosystem permits, then allow known required scripts explicitly. Install hooks execute code before your project compiles and often receive the runner's filesystem and environment.

## Triage vulnerabilities by exposure

Automated scanners identify known vulnerable versions, but severity alone does not tell you the application's risk. For each advisory, determine:

- direct or transitive dependency
- production, development, test, or build-only scope
- whether the vulnerable code path is imported and reachable
- whether attacker-controlled input can reach it
- privileges and data available at runtime
- fixed version and compatibility cost

Prioritize reachable vulnerabilities on exposed paths over unreachable high-scoring findings. Document time-bounded exceptions with evidence, owner, compensating controls, and expiry. Never turn a noisy scanner into a permanently ignored gate.

The [Dependency Audit](/skills/security/dependency-audit) automates this reachability-aware triage.

## Treat CI as a production system

CI can modify source, publish packages, sign artifacts, deploy workloads, and read secrets. Harden it accordingly:

- protect workflow and build-definition changes with code ownership
- pin external actions and reusable workflows to immutable revisions
- pin and scan build images
- separate untrusted pull-request testing from trusted release jobs
- prevent forked code from receiving release credentials
- use short-lived workload identity instead of long-lived secrets
- grant each job only the repository, package, cloud, and environment permissions it needs
- require protected environments and approval for production promotion
- isolate runners and destroy state after untrusted builds
- retain tamper-resistant logs for release actions

Avoid combining build and release authority in one broadly privileged job. Build an artifact in a constrained environment, then promote that immutable artifact through a separately authorized step. Rebuilding during deployment creates a new, less reviewed artifact.

## Protect secrets and signing identity

Secrets can leak through logs, test output, artifacts, caches, environment dumps, or malicious build code. Minimize how many jobs receive them and redact at the logging boundary.

Prefer identity federation and short-lived tokens tied to job, repository, branch, and environment. Rotate long-lived credentials out of CI. Store signing keys in managed hardware or signing services when the risk justifies it, and separate who can request a signature from who can change the build.

Scan source and history for committed credentials, but assume detection can fail. Design credentials with narrow scope, short lifetime, and rapid revocation.

## Generate provenance and an SBOM

A release should answer:

- What source revision produced this artifact?
- Which workflow and build environment ran?
- Which dependencies and base images are included?
- Who or what authorized the build and promotion?
- Has the artifact changed since it was produced?

Generate checksums, signed provenance, and a software bill of materials from the actual release build. Sign immutable artifacts, not mutable tags. Verify identity and policy when artifacts enter a registry, environment, or deployment system.

An SBOM accelerates incident scoping by listing components and versions. Provenance ties the artifact to its build. A signature protects integrity and identity. None alone proves absence of malicious code; together they make the chain auditable.

## Secure containers and deployment inputs

Pin base images by digest for reproducible releases, rebuild them regularly to incorporate security updates, and keep runtime images minimal. Separate build tools from the final image, run as a non-root user, and drop capabilities and writable paths not required by the application.

Scan infrastructure modules, deployment charts, and policy bundles as supply-chain inputs too. A trusted application image deployed through a compromised chart or mutable Terraform module is not a trusted release.

## Prepare for upstream compromise

Assume a dependency, maintainer account, registry, action, or signing credential will eventually be compromised. Practice the response:

1. Identify every affected product and artifact from inventory and SBOM data.
2. Block the package, version, action, image, or credential at the control point.
3. Revoke and rotate exposed identities.
4. Determine whether malicious code executed during build or runtime.
5. Rebuild from a clean source and trusted toolchain.
6. Verify new provenance and signatures.
7. Redeploy or republish in priority order.
8. Notify customers and partners with evidence-based scope.

Measure how long these steps take. An inventory that cannot answer “where is version X deployed?” during an incident is documentation, not response capability.

> [!WARNING]
> Automatically merging dependency updates is safe only when the update path, package source, tests, permissions, and release process are controlled. Automation reduces patch delay but also accelerates a compromised upstream package.

Use the [Dependency Manager](/agents/developer-tools/dependency-manager) for controlled upgrades, the [License Compliance Checker](/skills/security/license-compliance-checker) for distribution risk, and the [Secret Scanner](/skills/security/secret-scanner) to harden the credential layer of the chain.

---

_Source: https://agentscamp.com/guides/ai-safety/software-supply-chain-security — Guide on AgentsCamp._
