Dependency pinning limits what a package manager or build system may select. The constraint can name an exact version, an allowed version range, a source commit, or an immutable artifact digest. The chosen form determines how much change can enter without a deliberate update.
Where versions are constrained
Projects commonly declare version requirements in a package manifest and record resolved versions in a lockfile. Those files serve different purposes. A manifest expresses what versions are acceptable. A lockfile records the complete graph chosen for one resolution, including each transitive dependency.
Containers and remote build inputs can also be pinned. A moving tag names whatever artifact currently owns that tag, while a digest identifies a specific artifact. Source dependencies may point at a branch, tag, or commit. An audit distinguishes these mechanisms instead of treating every version-looking string as equivalent.
| Reference | Change allowed automatically | Evidence it provides |
|---|---|---|
| Broad version range | Any matching release | Declared compatibility intent |
| Exact package version | No version change | Selected direct version |
| Lockfile entry | No graph change until resolution | Selected direct and indirect versions |
| Source commit | No source revision change | Repository state selected |
| Artifact digest | No artifact change | Exact content selected |
Stability and updates are separate controls
Pinning makes resolution predictable. It does not make the selected version secure or maintained. A fixed vulnerable version stays vulnerable until somebody updates it. A broad range may receive a fix automatically, but it may also introduce behaviour the application has not tested.
A workable policy therefore combines several actions:
- Constrain inputs: Use a reference precise enough for the build's risk.
- Review changes: Make version and lockfile changes visible in code review.
- Verify integrity: Confirm that downloaded artifacts match expected sources or digests.
- Test updates: Run relevant tests before accepting the new graph.
- Refresh deliberately: Monitor known issues and schedule dependency updates.
What an audit looks for
An audit of vibe-coded software compares manifests, lockfiles, build files, and deployment configuration. It checks whether production builds use the committed lockfile, whether mutable tags or branches remain in critical inputs, and whether automated updates are paired with review and tests.
Software composition analysis identifies the versions currently present. Pinning explains whether the same versions will be selected again. Both contribute to the wider dependency risk assessment.
What good evidence looks like
A repeatable build has a documented set of inputs and a controlled way to change them. The repository shows who changed a dependency, the build identifies what it consumed, and tests show which behaviour was checked after the change.
Generated code can create a working manifest quickly without establishing that update path. Moving from a prototype to the practices described in what changes when software ships means treating dependency resolution as maintained production configuration.