Dependency Pinning
Dependency pinning is the practice of specifying the exact version of each software library or package your application depends on, rather than allowing a range of versions. This helps ensure that builds are reproducible and that unexpected or potentially malicious updates to a dependency are not automatically pulled into your project. It is a foundational practice for managing software supply chain risk.
Dependency pinning refers to explicitly declaring the precise version (or, in stricter implementations, the specific release number, git tag, or content hash) of each direct and transitive dependency in a project's dependency manifest or lock file. Rather than using version ranges or floating constraints (e.g., semver ranges like ^1.2.3 or ~1.2.0), pinning locks each dependency to a known-good version. This practice reduces the risk of supply chain attacks that exploit automatic version resolution, such as dependency confusion or compromised upstream releases. Pinning exists on a spectrum of strictness: at the least strict end, a dependency may be pinned to a branch or release series; at the stricter end, it is pinned to an exact release number, git commit, or cryptographic digest. While pinning improves build reproducibility and limits exposure to unexpected changes, it does not by itself verify the integrity or provenance of the pinned artifact, and it introduces a maintenance burden, as pinned versions must be actively monitored and updated to incorporate security patches.
Why it matters
Dependency pinning is a foundational defense against a class of software supply chain attacks that exploit automatic version resolution. When projects use floating version ranges (such as semver ranges like ^1.2.3 or ~1.2.0), build systems may silently pull in newer versions of dependencies without any deliberate action by the development team. If an upstream package is compromised or a malicious version is published (as in dependency confusion attacks), projects using unpinned dependencies can automatically incorporate that malicious code into their builds. By pinning to exact versions, teams create a deliberate gate that prevents unexpected updates from flowing into their software without review.
Beyond security, dependency pinning is essential for build reproducibility. Without pinning, two builds of the same codebase run at different times may resolve to different dependency versions, leading to inconsistent behavior, difficult-to-diagnose bugs, and unreliable testing. Reproducible builds are a prerequisite for meaningful security auditing, since teams need confidence that the artifacts they audit match what is actually deployed.
However, pinning is not without trade-offs. Pinned versions must be actively monitored and updated to incorporate security patches; otherwise, teams risk running known-vulnerable versions indefinitely. Pinning also does not, by itself, verify the integrity or provenance of the pinned artifact. It is best understood as one layer in a broader supply chain security strategy, complemented by practices such as hash verification, provenance attestation, and automated dependency update tooling.
Who it's relevant to
Inside Dependency Pinning
Common questions
Answers to the questions practitioners most commonly ask about Dependency Pinning.