Secure Package Version Pinning for npm, Bun, and pnpm
How to install an approved JavaScript dependency at an exact version, keep the lockfile authoritative, and update security patches deliberately.
Short answer
For a newly approved direct dependency, specify an exact version in package.json and commit the matching lockfile. Exact pins make the intended version reviewable; the lockfile fixes the complete transitive tree. Update either only after reviewing the security and compatibility impact.
Why a lockfile alone is not enough
A lockfile gives a repository reproducible installs today. The direct version in package.json still communicates what the project deliberately depends on. A range such as ^3.2.1 permits future compatible releases when the lockfile is regenerated; an exact version makes that future change an explicit pull-request decision.
This is especially useful when an AI coding tool proposes a package. The reviewer can approve a specific artifact rather than an open-ended range.
Install an exact approved version
Use only the package manager already used by the repository.
# npm
npm install <package-name>@<approved-version> --save-exact
# Bun
bun add <package-name>@<approved-version> --exact
# pnpm
pnpm add <package-name>@<approved-version> --save-exact
Then review both package.json and the package manager's lockfile. A direct dependency can be pinned while its transitive dependencies remain resolved in the lockfile; do not copy another manager's lockfile into the repository just to run a different command.
Pinning is not “set and forget” security
Exact versions reduce accidental drift. They do not remove the need to patch vulnerabilities. When an advisory arrives:
- Run the repository's audit command and identify the dependency path.
- Upgrade the direct parent to a reviewed patched version where possible.
- Use a documented, temporary override only when a compatible parent update is unavailable.
- Regenerate the lockfile, rerun audit and tests, then review the diff.
Do not turn a security response into an unreviewed migration with --force or --latest.
CI must enforce the reviewed graph
# npm
npm ci
# Bun
bun ci
# pnpm
pnpm install --frozen-lockfile
These commands ensure CI installs the reviewed lockfile rather than silently producing a new dependency tree.
For the complete audit-and-remediation loop, see JavaScript Dependency Security: Managing Vulnerabilities with npm, Bun, and pnpm. For the approval rules that should govern AI-proposed packages, see Supply-Chain Security in the AI Coding Era.
Ask AI About the Author
Open this query in ChatGPT, Claude, or Perplexity.
Comments
Comments are open to confirmed email subscribers. Use the email you subscribed with. To edit a comment, delete it and post a new one.
Subscribe to get the new blogs.
Field notes from someone who ships before they write about it. Sovereign AI, AI-SDLC, DevOps, and what 59 production deployments teach you. No spam. Unsubscribe anytime.