Skip to content

[RRFC] Ability to override --min-release-age on CLI or in the lockfile #856

@ericcornelissen

Description

@ericcornelissen

Motivation ("The Why")

I want to use the --min-release-age or --before option and I want to do so consistently so I set it in my .npmrc (former) or alias the npm command (latter). I also sometimes want a more recently published package - e.g., because of a vulnerability or because I request a new feature that was finally released. These two things are at odds with each other, and unfortunately --min-release-age and --before are all-or-nothing. Therefore, I would like to propose two "exceptions" for these options1:

  • If a package version is explicitly recorded in the lockfile it will be installed regardless of the minimum age requested.
  • If a package version is explicitly requested, e.g. npm install package@1.2.3 where v1.2.3 was released today, it will be installed regardless of the minimum age requested.

Prior Art

pnpm and yarn

Both of these have the ability to explicitly list exceptions (through minimumReleaseAgeExclude and npmPreapprovedPackages resp.) which bypass the minimum release age check. This is an alternative strategy to the one described here. The disadvantage is that it's a separate list that needs to be maintained, most notably the exceptions should (in most cases) be removed after they're no longer necessary, especially in the described scenario2.

Other Ecosystems

The Rust/Cargo proposal for its --min-release-age option (linked below) includes a similar concept:

  • Unless --precise is used to specify a specific version, any crates updated from the registry will only consider versions published
    before the time specified by the appropriate min-publish-age option. If --precise is used, that version will be used, even if it
    newer than the policy would otherwise allow (although in the future, there may be an option to deny that).
  • If the version of a crate in the lockfile is already newer than min-publish-age, then cargo update will not update that crate, nor will
    it downgrade to an older version. It will leave the version as it is.

Limitations

One drawback of this approach is that using an untrusted lockfile - e.g. from an untrusted repository or Pull Request - may unexpectedly override your expected security preferences. An attacker could leverage the suggested behavior to inject a malicious dependency into the lockfile and make you download it.

I believe that

  1. This attack is already possible by configuring/overriding the --min-release-age through a project level .npmrc 3.
  2. This is a trade-off that is worth considering as making the security feature more approachable in this way can help adoption, which might offset the risk of this thread.

Example

  • There is a vulnerability in a package and the fix was published today and I want to start using it now, so I run npm install vulnerable-but-now-fixed@4.2.0.
  • I contributed a bug fix or feature upstream and now want to use it myself as soon as possible, so I run npm install excited-to-use@3.1.4.
  • I, or someone on my team, has done one of the above and now I try to (re)install dependencies with npm clean-install where I don't want to get an error because of these newer dependencies.

How

Current Behaviour

If you want to use any new package you need to disable --min-release-age/--before entirely, affecting all packages.

Desired Behaviour

Using --min-release-age/--before is the default with explicitly recorded exceptions (through CLI arguments or the lockfile) to the rule.

References

Footnotes

  1. or possibly only one of them, as I feel this idea might make less sense for the intended use case of the --before option.

  2. exceptions make more sense for especially trusted packages such as internal/company packages or highly trusted packages such as, idk, express(?)

  3. further motivating the consideration for limiting this behavior to --min-release-age and not using it for --before.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions