A package.json with "some-library": "latest" or "another-lib": "*" means a fresh npm install six months from now could pull a breaking major version — silently. CWE-1357 applies: the project depends on whatever happens to be newest, not on a version it was tested against. SSDF PS.3 requires version-pinning as a supply chain control. This failure mode is especially dangerous in CI/CD pipelines that run npm install without a lockfile — a new release of a dependency can break production deployments without any code change.
Medium because wildcard or unbounded version specifiers allow untested breaking changes to be silently installed on any fresh `npm install`, turning a routine deploy into a potential breakage.
Replace every *, latest, and unbounded >= specifier with a pinned or caret range:
// Before (dangerous):
"dependencies": {
"some-library": "latest",
"another-lib": "*"
}
// After (safe):
"dependencies": {
"some-library": "^2.4.1",
"another-lib": "^1.0.0"
}
Run npm install after updating specifiers to regenerate the lockfile, then commit both package.json and package-lock.json together. Caret ranges (^X.Y.Z) allow minor and patch updates but block major version jumps.
ID: code-maintainability.dependency-management.version-specifiers
Severity: medium
What to look for: Examine the version specifiers in package.json for production dependencies. Look for:
* or latest — installs whatever is newest, including major breaking changes>= X.Y.Z with no upper bound — allows any version including future majors^X.Y.Z on packages with poor semver hygiene (i.e., packages that ship breaking changes in minor versions)Note: ^X.Y.Z (caret) is generally acceptable for well-behaved packages as it allows minor/patch updates but not major. ~X.Y.Z (tilde, patch only) is more conservative. Flag *, latest, and >= X as violations.
Pass criteria: Enumerate all version specifiers in production dependencies. All production dependencies use specific versions (X.Y.Z), caret ranges (^X.Y.Z), or tilde ranges (~X.Y.Z). No more than 0 bare * or latest or unbounded >= specifiers. Report the count: "X of Y production dependencies use safe version specifiers."
Fail criteria: One or more production dependencies use *, latest, or an unbounded >= version specifier. Do NOT pass when a specifier like >=1.0.0 appears without an upper bound — this permits arbitrary future major versions.
Skip (N/A) when: The project has no package.json. Signal: no package.json present.
Detail on fail: "2 production dependencies use 'latest' specifier: 'some-package': 'latest'. This means npm install after 6 months could install a breaking major version." or "'react': '*' — wildcard specifier allows any version including hypothetical future React 20+ with breaking changes."
Remediation: Version specifiers determine what gets installed on a fresh npm install. * or latest means an npm install six months from now could install a breaking change:
// Before (dangerous):
"dependencies": {
"some-library": "latest",
"another-lib": "*"
}
// After (safe):
"dependencies": {
"some-library": "^2.4.1",
"another-lib": "^1.0.0"
}
Run npm install with pinned versions, then commit the updated package.json and lock file together.