How Supply Chain Risk from Missing Package Age Validation Happens in pnpm and How to Fix It
Introduction
In the pnpm-workspace.yaml configuration file of a Node.js library, a critical supply chain security control was missing: the minimumReleaseAge setting. This oversight created a window of vulnerability where malicious actors could publish compromised packages to npm, and those packages would be installed immediately by any project using this workspace configuration—before the security community had time to detect and flag the malicious code.
This isn't a code execution vulnerability in the traditional sense. Instead, it's a configuration gap that removes a crucial defense mechanism against one of the most prevalent attack vectors in modern software development: the supply chain attack through compromised or malicious npm packages.
The fix was straightforward but critical: adding four lines to pnpm-workspace.yaml to enforce a 7-day grace period before any newly published package versions can be installed. Let's explore why this matters and how to implement it in your own projects.
The Vulnerability Explained
What Happened
The original pnpm-workspace.yaml file looked like this:
packages:
- 'packages/*'
allowBuilds:
esbuild: true
unrs-resolver: true
Notice what's missing: there's no settings section, and specifically, no minimumReleaseAge configuration. This means that when pnpm resolves dependencies, it will install newly published package versions immediately upon release—without any waiting period.
Why This Is Dangerous
Consider this attack scenario:
- An attacker compromises a popular npm package (or creates a typosquatting package with a similar name)
- They publish a malicious version to npm at 2:00 PM UTC
- Your CI/CD pipeline runs a fresh install at 2:05 PM UTC
- Before any security researcher, npm security team, or community member has time to analyze the package, your project has already downloaded and potentially executed the malicious code
- By the time the malicious package is detected and flagged (often 24-48 hours later), the damage is done
This attack pattern has been documented in real-world incidents:
- Dependency confusion attacks (like the 2021 Alex Birsan research) rely on rapid package installation
- Typosquatting campaigns depend on catching developers before they realize the mistake
- Compromised maintainer accounts can push malicious versions that spread before detection
The minimumReleaseAge setting creates a mandatory 7-day buffer that gives the security community time to:
- Analyze newly published packages
- Run security scans
- Detect anomalies in package behavior
- Report malicious packages to npm
- Allow npm to remove or yank the version
The Real-World Impact
For a Node.js library (as indicated in the PR context), this vulnerability affects all downstream consumers. If your library is used by other projects, they inherit this supply chain risk. A malicious transitive dependency could compromise not just your project, but every application that depends on your library.
The Fix
The pull request added the following configuration to pnpm-workspace.yaml:
packages:
- 'packages/*'
allowBuilds:
esbuild: true
unrs-resolver: true
+
+minimumReleaseAge: 10080
+blockExoticSubdeps: true
+trustPolicy: no-downgrade
Breaking Down Each Change
1. minimumReleaseAge: 10080
This is the primary security fix. The value 10080 represents 10,080 minutes, which equals exactly 7 days. With this setting enabled:
- pnpm will refuse to install any package version published fewer than 7 days ago
- If a package was published on Monday, it cannot be installed until the following Monday
- This gives the npm security community a full week to identify and report malicious packages
The 7-day window was chosen as a balance between:
- Security: Long enough for researchers to analyze packages and report issues
- Practicality: Short enough that legitimate security updates don't face unreasonable delays
2. blockExoticSubdeps: true
This complementary setting prevents pnpm from installing packages with unusual or suspicious dependency structures. It blocks:
- Packages with circular dependencies
- Packages with overly complex dependency trees
- Packages with dependencies on unregistered registries
3. trustPolicy: no-downgrade
This prevents pnpm from installing older versions of packages when newer versions are available. This protects against attacks where an attacker publishes a malicious older version (which might have fewer security checks) and tricks the package manager into downgrading.
How This Solves the Problem
Before the fix:
Package published → Immediately installable → Malicious code executes before detection
After the fix:
Package published → 7-day waiting period → Security analysis + detection → Safe installation OR version yanked
The three settings work together to create defense in depth:
1. minimumReleaseAge delays installation of new versions
2. blockExoticSubdeps prevents unusual dependency patterns
3. trustPolicy: no-downgrade prevents downgrade attacks
Prevention & Best Practices
1. Enable minimumReleaseAge in All Workspace Configurations
Add this to every pnpm-workspace.yaml:
settings:
minimumReleaseAge: 10080
Or for individual projects using pnpm-config.yaml / .npmrc:
minimum-release-age=10080
2. Adjust the Delay Based on Your Risk Profile
While 7 days (10,080 minutes) is recommended:
- High-security environments (financial services, healthcare): Consider 14 days (20,160 minutes)
- Standard projects: Use 7 days (10,080 minutes)
- Development-only: Can use shorter delays, but production builds should use the full 7 days
3. Combine with Other Supply Chain Controls
minimumReleaseAge is one layer of defense. Combine it with:
- Dependency pinning: Use exact versions in
package-lock.json/pnpm-lock.yaml - Supply chain attestation: Use npm's provenance feature to verify package authenticity
- Security scanning: Run
npm auditand use tools like Snyk or Dependabot - Private registries: For high-security environments, mirror dependencies on a private npm registry with additional vetting
- Signature verification: Verify package signatures where available
4. Detect Missing minimumReleaseAge with Static Analysis
Use Semgrep to automatically detect this configuration gap:
semgrep --config p/security-audit --config p/package-managers pnpm-workspace.yaml
Or specifically for this rule:
semgrep --config p/package_managers.pnpm.pnpm-missing-minimum-release-age pnpm-workspace.yaml
5. Document Your Supply Chain Policy
Add this to your project's security documentation:
## Package Installation Policy
This project enforces a 7-day minimum release age for all npm packages.
- Configured in: `pnpm-workspace.yaml`
- Setting: `minimumReleaseAge: 10080`
- Rationale: Allows security community time to identify malicious packages
- Exceptions: None. All production builds must respect this delay.
Key Takeaways
- pnpm's
minimumReleaseAgeis not enabled by default, creating a supply chain vulnerability where newly published packages—potentially malicious—can be installed immediately - The 7-day delay (10,080 minutes) is a critical control, not a performance optimization—it's your defense against rapid supply chain attacks
- This vulnerability affects downstream consumers: If your library lacks this setting, every project using your library inherits the risk
- The fix is configuration-only: No code changes required, but the security impact is significant
- Combine with defense-in-depth: Use
minimumReleaseAgealongside lockfiles, security scanning, and signature verification for comprehensive supply chain protection
How Orbis AppSec Detected This
Source: The pnpm-workspace.yaml configuration file, which defines workspace-level security settings for all package installations
Sink: The missing settings.minimumReleaseAge configuration option that controls whether pnpm enforces a grace period before installing newly published packages
Missing Control: No validation that minimumReleaseAge is configured; the workspace allowed installation of packages from any release age without restriction
CWE: CWE-345 (Insufficient Verification of Data Authenticity) — the system fails to verify the trustworthiness of newly published package versions before installation
Fix: Added minimumReleaseAge: 10080 to pnpm-workspace.yaml to enforce a mandatory 7-day waiting period before any newly released package versions can be installed, allowing the security community time to identify and report malicious packages
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
Supply chain security is no longer optional—it's a fundamental requirement for any project that depends on third-party packages. The missing minimumReleaseAge setting in pnpm represents a common oversight: a configuration gap that removes a critical defense mechanism without adding any legitimate value.
The fix is simple (four lines of YAML), but the security impact is profound. By enforcing a 7-day grace period before package installation, you give the npm security community—and your own security team—time to identify and respond to malicious packages before they reach production.
This is especially critical for libraries and frameworks, where a single compromised dependency can affect thousands of downstream projects. Start by adding minimumReleaseAge: 10080 to your pnpm-workspace.yaml today, and encourage your dependencies to do the same.
References
- CWE-345: Insufficient Verification of Data Authenticity — https://cwe.mitre.org/data/definitions/345.html
- OWASP Supply Chain Security — https://owasp.org/www-community/attacks/Supply_chain_attack
- pnpm Documentation: minimumReleaseAge Setting — https://pnpm.io/settings#minimumreleaseage
- pnpm v10.16.0 Release Notes — https://github.com/pnpm/pnpm/releases/tag/v10.16.0
- Semgrep Rule: pnpm Missing Minimum Release Age — https://semgrep.dev/r?q=package_managers.pnpm.pnpm-missing-minimum-release-age
- npm Security Advisories — https://docs.npmjs.com/about-npm-advisories
- GitHub PR: harden: this pnpm workspace configuration does not set ... in... — harden: this pnpm workspace configuration does not set ... in...