Skip to content

Conversation

@PR3C14D0
Copy link

@PR3C14D0 PR3C14D0 commented Dec 3, 2025

Summary

This PR implements a minimum package age policy feature for npm, similar to pnpm's minimumReleaseAge (pnpm/pnpm#9921). This security feature helps protect against supply chain attacks where malicious package versions are published and then quickly removed from the registry.

Motivation

Recent supply chain attacks have shown that malicious actors often publish compromised versions of popular packages and remove them within hours after causing damage. By enforcing a minimum age requirement, users can avoid installing versions that haven't been publicly available long enough to be vetted by the community.

Changes

New Configuration Options

  • minimum-release-age (Number, default: 0)

    • Specifies the minimum age in minutes that a package version must have before it can be installed
    • When set to 0, the policy is disabled (default behavior)
  • minimum-release-age-exclude (Array, default: [])

    • List of package names that should bypass the minimum age policy
    • Useful for trusted packages where immediate updates are needed

Implementation Details

  1. Configuration - Added definitions for both new options in the config definitions module
  2. Dependency Resolution - Modified the manifest fetching logic in Arborist to:
    • Fetch full packument to access version timestamps
    • Calculate cutoff time based on configured age
    • Add recent versions to pacote's avoid option
    • Gracefully handle errors (skips policy if packument fetch fails)
  3. Documentation - Added comprehensive documentation with usage examples
  4. Tests - Added 4 test cases with 9 assertions covering all scenarios

Usage Examples

Via .npmrc:

minimum-release-age=1440  # 24 hours
minimum-release-age-exclude[]=@myorg/trusted-package

Via CLI:

npm install --minimum-release-age=10
npm install some-package --minimum-release-age=60 --minimum-release-age-exclude=critical-package

Via environment variable:

npm_config_minimum_release_age=10 npm install

Testing

All tests pass:

✓ 4 test suites (9 assertions)
✓ Linting passes

Test coverage includes:

✅ Basic policy enforcement (avoids recent versions)
✅ Exclusion list functionality
✅ Disabled policy (minimum-release-age=0)
✅ Error handling (packument fetch failures)

Breaking changes

None. This is a purely additive feature with default behavior unchanged (policy disabled by default).

Related issues

Inspired by pnpm/pnpm#9921

Add support for minimum-release-age configuration option to enforce
a waiting period before installing newly published package versions.
This helps mitigate supply chain attacks where malicious versions are
published and quickly removed.

Changes:
- Add minimum-release-age config option (default: 0, disabled)
- Add minimum-release-age-exclude config option for exemptions
- Implement version filtering in Arborist's #fetchManifest method
- Add comprehensive test coverage (4 tests, 9 assertions)

The policy works by:
1. Fetching the full packument for each package
2. Calculating a cutoff time based on the configured age
3. Identifying versions released after the cutoff
4. Adding them to the 'avoid' range passed to pacote

Users can configure via .npmrc, CLI flags, or environment variables:
  minimum-release-age=10
  minimum-release-age-exclude[]=critical-package

Files modified:
- workspaces/config/lib/definitions/definitions.js
- workspaces/arborist/lib/arborist/build-ideal-tree.js
- workspaces/arborist/test/arborist/minimum-release-age.js (new)

Inspired by pnpm's minimumReleaseAge feature (pnpm/pnpm#9921)
Add documentation for:
- minimum-release-age configuration
- minimum-release-age-exclude configuration
- Usage examples and security benefits"
@wraithgar
Copy link
Member

This is already being explored in an existing PR #8802

@wraithgar wraithgar closed this Dec 3, 2025
@loudar
Copy link

loudar commented Dec 4, 2025

This is already being explored in an existing PR #8802

The other PR doesn't seem to have an option to exclude specific packages from the rule though?

@passee
Copy link

passee commented Dec 4, 2025

@wraithgar there is no exclude option available in the pr you mentioned

@PR3C14D0
Copy link
Author

PR3C14D0 commented Dec 4, 2025

This is already being explored in an existing PR #8802

The PR #8802 it does not have an exclude package option. Mine is a minimal implementation that can be extended during the time and improve it and maybe an implementation at package.json.

I would consider accepting this pull request and not closing it immediately as you did, and extending the implementation. It's one of the most requested security policies in recent times.

@fabianmartinezcaro
Copy link

fabianmartinezcaro commented Dec 5, 2025

thi shit is more robust than #8802, fr fr. @PR3C14D0 congrats bro

@fabianmartinezcaro
Copy link

fabianmartinezcaro commented Dec 5, 2025

Speechless, bro is cooking

@mikkelee
Copy link

mikkelee commented Dec 5, 2025

I vote for all pull requests that implement a quarantine period and allow specifying packages that can skip quarantine. I have no opinion on the naming of the configuration keys because I will not be looking at them more than once a month at most. To be clear, and in case of ties with other pull requests: consider this a vote for the concept in general and all of them together.

@PR3C14D0
Copy link
Author

PR3C14D0 commented Dec 5, 2025

I vote for all pull requests that implement a quarantine period and allow specifying packages that can skip quarantine. I have no opinion on the naming of the configuration keys because I will not be looking at them more than once a month at most. To be clear, and in case of ties with other pull requests: consider this a vote for the concept in general and all of them together.

Anyways, this is not a competition hmmm ☹️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants