#500

Fix npm release selection and false-clean install-script reports

Opene-qopened 3d ago

The supply-chain risk auditor can describe the wrong npm release and report that a dependency has no install script when its registry metadata contains one. This affects the reliability of the report's deprecation, install-script, and publish-provenance results.

PR #497 by @robertaustinbell identified the release-version mismatch and contributed regression tests for selected-versus-latest metadata. Thanks to Austin Bell for reporting and proposing a fix. This issue captures that bug together with the related metadata-format and availability problems found while reviewing the PR.

What goes wrong

Release properties come from latest, even when the project selects an older release

The collector resolves a dependency's version from a lockfile or an exact manifest pin, but npm_metadata() reads deprecation, install-script status, and provenance from dist-tags.latest. The report displays those properties beside the selected version.

For example, a project pinned to uuid@3.4.0 should receive the deprecation warning for that release. The registry marks that release deprecated and the current latest release supported. Reading the latest release's metadata incorrectly makes the pinned dependency appear not deprecated. The reverse also produces false warnings: a property introduced in a newer release is attributed to an older installed release.

Exact npm selectors can also lose their version before metadata is read. An alias such as npm:@scope/package@1.0.0 without a lockfile, or an exact selector with npm's supported v or = prefix, is treated as unresolved and falls back to latest. npm also canonicalizes leading zeroes in exact versions and numeric prerelease identifiers. A literal registry-key lookup does not handle those accepted forms.

Install scripts are read from a field absent from the requested response format

The collector requests npm's full package metadata and reads hasInstallScript. npm documents that field in its abbreviated installation metadata; the full version manifests expose scripts instead.

Full metadata for esbuild and core-js contains scripts.postinstall and lacks hasInstallScript. The collector converts the absent field to False, then reports "no install script". Selecting the correct version alone does not repair this result.

Detection must distinguish the dependency lifecycle hooks that execute during registry installation from unrelated scripts such as test, build, and prepare. npm can also supply an implicit native build through node-gyp; the collector must state what its metadata can establish without downloading or executing packages.

Missing latest metadata discards information that is still available

npm_metadata() rejects the entire response when latest is absent or refers to a missing version. A selected release can still be present, and the response can still contain current maintainers and repository information. Those measurements should remain available. The latest release's provenance, used by the publisher assessment, can independently be unknown.

Expected behavior

  • Read release properties from the resolved dependency version. Preserve the documented latest-release fallback when no exact version is available, and identify that fallback in the report.
  • Preserve exact selectors inside npm aliases and match them using npm's version normalization. For example, v1.0.0, =1.0.0, and 1.0.0+build.7 resolve to the registry release 1.0.0; prerelease identifiers must remain significant.
  • When the selected release is unavailable, mark its properties unassessable with a reason. Do not substitute another release's values.
  • Read install-time behavior from metadata appropriate to the response format. Do not equate an absent field in another format with evidence that no script runs.
  • Keep current maintainer information and the publisher assessment separate from the historical selected release. Missing latest-release provenance must remain unknown rather than becoming a negative provenance measurement.
  • Preserve independently available package, release, download, and repository measurements when another measurement is unavailable.
  • Keep the audit metadata-only: do not install, build, execute, or fetch dependency source to obtain these results.

Regression coverage

Use offline registry fixtures with the documented full-metadata shape. Vary deprecation, scripts, and provenance independently so that reading one property from another cannot pass the tests. Cover selected/latest disagreements, missing selected releases, absent or dangling latest tags, exact pins without a lockfile, lockfile precedence, and version normalization. Include collector-to-report coverage so that incorrect values cannot be hidden by rendering.

Sources

Activity

1
e-q3d ago

Draft implementation: #501.

The PR includes selected-release lookup, exact npm selector and alias normalization, full-metadata install-hook detection, independent handling of unavailable measurements, and updated report/documentation scope. It also includes an adversarial subagent review, fixes for its findings, and offline regression coverage. The PR remains in draft pending full validation.