Skip to content
oss-kit
Install

Registry dependencies resolve through a committed lockfile

Rule
R-SEC-08
Area
Security posture · 8 of 15
Forge scope
GitHub and GitLab
Fixed by
oss-harden

A version range re-resolves on every build, so what CI installs today is not what it installed yesterday. A lockfile records the exact artifact and its hash, which turns a silent substitution into a failed build. It costs a maintainer nothing, because the package manager writes it.

Observable check

the lockfile or fully hashed requirements file the project's package manager produces is committed, records integrity for registry dependencies, and every CI install uses the package manager's current frozen mode so it fails on stale or missing resolution data rather than updating it. Two clauses narrow it, and both key on what the tooling documents rather than on what the repository happens to contain, so an absent lockfile is never mistaken for an impossible one. Where the project's build tool publishes no lockfile format at all, the version-lock half falls outside this rule rather than failing it; among the ecosystems this standard covers that is Apache Maven, which offers fixed versions, dependencyManagement, and enforcer rules such as banDynamicVersions in place of one, and it is the build tool rather than the Maven Central registry that earns this, because a Gradle project publishing to the same registry writes gradle.lockfile and stays inside the rule. Where the ecosystem's own documentation directs a library package not to commit its lockfile, which both NuGet and Dart do, the rule reaches that ecosystem's application packages and the library case falls outside it rather than failing it.

Where this comes from

Last read against these sources on 2026-07-31.

Scorecard Pinned-Dependencies covers pinning to a hash rather than a range. No source named yet for the frozen-install half (npm ci, bundle install --deployment, uv sync --frozen). The two narrowing clauses were added on 2026-07-31 after reading the build tools themselves, and the reading corrected the assumption they were written on. The exemption keys on the build tool rather than the registry: Apache Maven publishes no lockfile format at all, opt-in or otherwise, and offers dependencyManagement plus enforcer rules such as banDynamicVersions in its place, while Gradle writes gradle.lockfile whose own generated header says it is expected to be part of source control and already fails a build on a version mismatch without an extra flag. Keying the exemption to Maven Central would therefore have handed it to every Gradle project publishing to the same registry. Even for Maven the exemption covers the version-lock half only, because Maven Resolver's Trusted Checksums record a committed coreutils-format hash file verified at resolution with failIfMissing, which is the hashed-file half this rule already accepts. The commit-convention clause is the second correction: NuGet and Dart both document that a library package should not commit its lockfile while an application should, so without the clause two ecosystems failed this rule for following their own upstream guidance. Retire either clause the day its tooling ships what it currently lacks.

Read the whole standard