Supply-Chain Security for Dependencies
A dependency is a trust decision beyond its current code — provenance, transitive dependency count, update risk, and install-time script execution all matter.
Purpose
Adding a dependency means trusting code you likely haven’t read, maintained by people you don’t control, that can change at any future install. A supply-chain threat model accounts for more than whether the currently-reviewed version’s code looks correct.
What to account for
- Provenance: can a published package be verifiably traced back to its claimed source repository and build process (npm’s provenance attestations, for instance), or is it trusted purely on the registry’s word?
- Update risk: a
^-prefixed version range allows an automatic update to pull in new code — malicious or merely broken — without explicit review at install time. - Transitive dependencies: a direct dependency’s own dependency tree is equally part of the trust surface, often numbering in the hundreds even for a modest application.
- Install-time code execution: npm lifecycle scripts (
postinstall, and others) run arbitrary code automatically on install — a real, historically-exploited attack vector, independent of whether the package’s main code is ever actually imported.
Behavior notes
- A lockfile (recall package.json and package-lock.json) guarantees reproducible installs — it does not mean the pinned versions were ever reviewed for malicious content.
npm audit(and equivalent tools) checks known-vulnerability databases against installed versions — useful, but only catches issues already publicly disclosed, not zero-day supply-chain compromises.- Minimizing total dependency count is itself a security practice: every dependency (and its own transitive tree) is additional trust surface, regardless of how well-reviewed any single one is.
Common mistakes
- Treating a lockfile as proof that dependencies are safe, rather than only that they’re reproducible.
- Adding a dependency for a small amount of functionality that could reasonably be written directly, expanding the trust surface for limited benefit.
Runtime notes
A practice concern for the npm/Node ecosystem specifically, though the underlying trust considerations apply to any package manager or dependency ecosystem.