Back to Blog
high SEVERITY8 min read

How missing minimum release age happens in pnpm workspaces and how to fix it

A pnpm workspace configuration was missing the `minimumReleaseAge` setting, meaning freshly published — and potentially malicious or unstable — npm packages could be installed immediately. By adding `minimumReleaseAge: 10080` to `pnpm-workspace.yaml`, the project now enforces a seven-day waiting period before any newly released package version can be installed. This single configuration change significantly reduces the attack surface for supply chain attacks targeting this Node.js library and it

O
By Orbis AppSec
Published July 27, 2026Reviewed July 27, 2026

Answer Summary

This vulnerability is a missing supply chain control in a pnpm workspace (CWE-1395: Dependency on Vulnerable Third-Party Component). The `pnpm-workspace.yaml` file lacked a `minimumReleaseAge` setting, allowing npm packages to be installed the moment they are published — before the community has had time to detect malicious or compromised versions. The fix adds `minimumReleaseAge: 10080` (7 days in minutes), `blockExoticSubdeps: true`, and `trustPolicy: no-downgrade` to the workspace configuration, enforcing a safety buffer against typosquatting, account-takeover, and dependency confusion attacks.

Vulnerability at a Glance

cweCWE-1395 (Dependency on Vulnerable Third-Party Component)
fixAdded `minimumReleaseAge: 10080` (7 days), `blockExoticSubdeps: true`, and `trustPolicy: no-downgrade` to `pnpm-workspace.yaml`
riskMalicious or unstable newly published packages can be installed automatically before community detection
languageYAML / Node.js (pnpm)
root cause`pnpm-workspace.yaml` did not set `minimumReleaseAge`, allowing zero-day package installations
vulnerabilityMissing Minimum Release Age in pnpm Workspace

How Missing Minimum Release Age Happens in pnpm Workspaces and How to Fix It


The Vulnerability at a Glance

Field Detail
Vulnerability Missing Minimum Release Age in pnpm Workspace
CWE CWE-1395 — Dependency on Vulnerable Third-Party Component
Language YAML / Node.js (pnpm)
Risk Malicious or unstable newly published packages installed automatically
Root Cause pnpm-workspace.yaml lacked minimumReleaseAge setting
Fix Added minimumReleaseAge: 10080, blockExoticSubdeps: true, trustPolicy: no-downgrade

Summary

A pnpm workspace configuration was missing the minimumReleaseAge setting, meaning freshly published — and potentially malicious or unstable — npm packages could be installed immediately. By adding minimumReleaseAge: 10080 to pnpm-workspace.yaml, the project now enforces a seven-day waiting period before any newly released package version can be installed. This single configuration change significantly reduces the attack surface for supply chain attacks targeting this Node.js library and its downstream consumers.


Introduction

The pnpm-workspace.yaml file is the control center for a pnpm monorepo. It defines which directories are workspace packages and — critically — governs the security policies that apply when resolving and installing dependencies across all of apps/* and packages/*. In this project, the file was doing its job of mapping workspace directories, but it was leaving a significant supply chain door wide open: there was no minimumReleaseAge setting, meaning pnpm would happily install a package version the instant it appeared on the npm registry, with zero waiting period.

This matters because supply chain attacks increasingly rely on that narrow window between publication and detection. Whether it's a typosquatted package name, a compromised maintainer account, or a malicious version bump, attackers count on automated CI pipelines pulling fresh packages before anyone notices something is wrong.


The Vulnerability Explained

What Was Missing

Here is the original pnpm-workspace.yaml before the fix:

packages:
  - "apps/*"
  - "packages/*"

Three lines. Functional, but completely silent on package vetting policy. Without minimumReleaseAge, pnpm operates with the implicit assumption that any version on the npm registry is safe to install the moment it is published.

Why This Is a Real Risk

The npm registry publishes tens of thousands of new package versions every day. The security community — including automated scanners, maintainers, and researchers — needs time to review new releases. The gap between "published" and "detected as malicious" is often measured in hours to days.

Three concrete attack vectors exploit this gap:

1. Account Takeover (ATO) Attacks
An attacker compromises a popular package maintainer's npm credentials and publishes a malicious patch version (e.g., some-util@2.3.1some-util@2.3.2). Any project running pnpm install within the first few hours after publication will pull the compromised version before npm or the security community has time to yank it.

2. Dependency Confusion
An attacker publishes a public package with the same name as an internal private package used in this monorepo (which covers apps/* and packages/*). Without a release age gate, the first pnpm install after publication could resolve to the attacker's version.

3. Typosquatting
A developer makes a typo in a new dependency name. The attacker has pre-registered that typo on npm with a malicious payload. Without a minimum release age, the malicious package installs immediately.

Why This Project Is Particularly Exposed

The PR notes this is a Node.js library — meaning vulnerabilities don't just affect the project itself, but propagate downstream to every consumer of the library. A supply chain compromise here has a multiplier effect: one poisoned install can affect dozens or hundreds of downstream projects.


The Fix

What Changed

The fix added three security settings to pnpm-workspace.yaml:

Before:

packages:
  - "apps/*"
  - "packages/*"

After:

packages:
  - "apps/*"
  - "packages/*"

minimumReleaseAge: 10080
blockExoticSubdeps: true
trustPolicy: no-downgrade

Breaking Down Each Change

minimumReleaseAge: 10080

This is the core fix. The value 10080 is the number of minutes in seven days (7 × 24 × 60 = 10,080). With this setting, pnpm will refuse to install any package version that was published less than seven days ago.

This seven-day window is deliberate and meaningful:
- npm's security team typically identifies and yanks malicious packages within hours to a few days
- Community security researchers and automated scanners have time to flag suspicious releases
- The project's own developers are more likely to notice unusual dependency updates in code review

This setting was introduced in pnpm v10.16.0 and is referenced in the official pnpm documentation.

blockExoticSubdeps: true

This setting prevents installation of dependencies that use non-standard or exotic resolution mechanisms — a common vector in dependency confusion and supply chain attacks where attackers exploit unusual package specifiers.

trustPolicy: no-downgrade

This prevents pnpm from silently downgrading the trust level of packages already in the workspace. Combined with minimumReleaseAge, it ensures that once a package version has been vetted and installed, it cannot be quietly replaced with a less-trusted version.

The Combined Effect

These three settings work together as a layered defense:

New package published on npm
        
        
┌─────────────────────────────┐
  minimumReleaseAge: 10080      Blocks install for 7 days
  (time-based vetting gate)  
└─────────────────────────────┘
         (after 7 days)
        
┌─────────────────────────────┐
  blockExoticSubdeps: true      Blocks non-standard resolution
└─────────────────────────────┘
        
        
┌─────────────────────────────┐
  trustPolicy: no-downgrade     Prevents trust regression
└─────────────────────────────┘
        
        
    Package installed 

Prevention & Best Practices

1. Enable minimumReleaseAge in All pnpm Projects

Any project using pnpm v10.16.0 or later should add this to pnpm-workspace.yaml or .npmrc:

# pnpm-workspace.yaml
minimumReleaseAge: 10080  # 7 days in minutes

For projects where a 7-day wait is too long (e.g., rapid iteration environments), consider a shorter but non-zero value:

minimumReleaseAge: 1440  # 1 day minimum

Even a 24-hour window catches many automated malicious publish attacks.

2. Use a Lockfile and Commit It

A pnpm-lock.yaml committed to your repository ensures that pnpm install in CI always installs the exact same versions. The minimumReleaseAge setting protects you when you update the lockfile — the lockfile protects you when you use it.

3. Enable Provenance and Audit in CI

Add these to your CI pipeline:

pnpm audit --audit-level=high

And consider enabling npm provenance for packages you publish, so consumers can verify the build origin.

4. Monitor Dependencies with Automated Tools

Tools like Dependabot, Renovate, and Socket.dev provide ongoing monitoring of your dependency tree for newly introduced risks.

5. Apply Defense-in-Depth for Supply Chain

The OWASP Software Component Verification Standard (SCVS) and SLSA framework provide structured guidance for supply chain security beyond just package manager settings.

Relevant Standards

  • CWE-1395: Dependency on Vulnerable Third-Party Component
  • OWASP A06:2021: Vulnerable and Outdated Components
  • SSDF PW.4: Reuse existing, well-secured software where feasible

Key Takeaways

  • pnpm-workspace.yaml is a security surface, not just a directory map. The absence of minimumReleaseAge in this file meant all apps/* and packages/* workspaces were exposed to zero-day package installations.
  • 10,080 minutes (7 days) is the recommended minimum. This specific value aligns with the typical detection window for malicious npm packages and is the value recommended by the pnpm team.
  • Three settings work better than one. The combination of minimumReleaseAge, blockExoticSubdeps, and trustPolicy: no-downgrade provides layered supply chain defense that no single setting achieves alone.
  • Library projects have amplified risk. Because this is a Node.js library with downstream consumers, a supply chain compromise here propagates further than it would in a standalone application — making this fix especially high-value.
  • This is a configuration gap, not a code bug. Static analysis tools like Semgrep can detect missing security configurations just as effectively as they detect vulnerable code patterns — don't limit your scanning to source code only.

How Orbis AppSec Detected This

  • Source: The pnpm-workspace.yaml file at line 1, which governs dependency resolution policy for all packages in the apps/* and packages/* workspace directories.
  • Sink: Any pnpm install or pnpm update invocation that resolves package versions — specifically, the absence of a time-based gate before newly published versions are accepted.
  • Missing control: The minimumReleaseAge setting was entirely absent from pnpm-workspace.yaml, meaning pnpm applied no waiting period to newly published package versions.
  • CWE: CWE-1395 — Dependency on Vulnerable Third-Party Component
  • Fix: Added minimumReleaseAge: 10080, blockExoticSubdeps: true, and trustPolicy: no-downgrade to pnpm-workspace.yaml, enforcing a 7-day vetting window and blocking non-standard dependency resolution.

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 attacks are one of the fastest-growing categories of security incidents in the npm ecosystem, and they specifically exploit the trust that package managers place in newly published versions. The missing minimumReleaseAge setting in this project's pnpm-workspace.yaml was a quiet but meaningful gap — one that required zero lines of malicious code to exploit, just a lucky timing window.

The fix is elegantly simple: three lines of YAML that enforce a 7-day waiting period, block exotic dependency resolution, and prevent trust downgrades. For a Node.js library with downstream consumers, this configuration change delivers outsized security value relative to its implementation cost.

The broader lesson for developers: your package manager configuration files are security policy documents. Treat them with the same scrutiny you'd apply to authentication middleware or input validation logic. A missing setting in pnpm-workspace.yaml can be just as dangerous as a missing bounds check in application code.


References

Frequently Asked Questions

What is a missing minimum release age in pnpm?

It means your pnpm workspace has no waiting period before installing newly published package versions. Without this setting, a malicious or compromised package can be pulled into your project the instant it appears on the npm registry.

How do you prevent missing minimum release age in pnpm?

Add `minimumReleaseAge: 10080` to your `pnpm-workspace.yaml` file. This requires pnpm v10.16.0 or later and enforces a 7-day (10,080-minute) delay before any newly published package version is eligible for installation.

What CWE is missing minimum release age?

It maps most closely to CWE-1395: Dependency on Vulnerable Third-Party Component, since the root issue is the unconditional trust and immediate use of third-party packages without any vetting delay.

Is locking dependency versions (lockfile) enough to prevent this?

A lockfile protects existing installs but does not protect you when you intentionally upgrade or add new packages. `minimumReleaseAge` adds a time-based safety buffer that a lockfile alone cannot provide.

Can static analysis detect missing minimum release age?

Yes. Semgrep rule `package_managers.pnpm.pnpm-missing-minimum-release-age.pnpm-minimum-release-age` detects the absence of this setting in `pnpm-workspace.yaml` automatically, as demonstrated in this fix.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #27

Related Articles

critical

How HTML sanitizer bypass via XMP tag passthrough happens in Node.js and how to fix it

A critical cross-site scripting (XSS) vulnerability in the sanitize-html library allowed attackers to bypass HTML sanitization through improper handling of the `<xmp>` raw-text element. This vulnerability could enable stored XSS attacks in any Node.js application using sanitize-html versions prior to 2.17.4. The fix involved upgrading the library to properly handle raw-text elements and prevent script injection.

high

How missing Dependabot cooldown happens in GitHub Actions and how to fix it

A Dependabot configuration in `.github/dependabot.yml` was missing cooldown periods for both GitHub Actions and npm package ecosystems. This high-severity misconfiguration could have allowed malicious or unstable newly-published packages to be automatically proposed for updates before the security community had time to identify threats. The fix adds a 7-day cooldown period to both package ecosystem entries.

high

How path traversal happens in Python open() and how to fix it

A high-severity path traversal vulnerability was discovered in `src/backend/snitch.py` where the `writeTestcase()` function accepted a user-controlled `portDir` parameter without sanitization. An attacker could craft malicious input like `../../etc` to write files outside the intended output directory. The fix implements path canonicalization using `pathlib.Path.resolve()` and validates that the final destination stays within the allowed base directory.

critical

How plaintext credential storage happens in Node-RED custom nodes and how to fix it

A critical security vulnerability was discovered in the `telegrambot/99-telegrambot.html` file where the Telegram bot token was registered as a Node-RED credential of type `'text'` instead of `'password'`. This meant the token was transmitted in plaintext over the admin API and stored without obfuscation in `flows_cred.json`, allowing attackers with filesystem or network access to recover the bot token and take full control of the Telegram bot.

critical

How weak PBKDF2 key derivation happens in Frida Android server and how to fix it

The Frida Android server used PBKDF2WithHmacSHA1And8BIT with only 128 iterations to derive secret keys for device attestation. This critically weak configuration made password brute-forcing trivial, allowing attackers who obtained the derived key to recover the original password in seconds. The fix upgraded to PBKDF2WithHmacSHA256 with 600,000 iterations, meeting modern cryptographic standards.

high

How Dependabot Missing Cooldown Periods Happen in GitHub Actions and How to Fix It

A missing cooldown period in Dependabot configuration creates a supply chain vulnerability by allowing automatic updates to newly published packages that could be malicious or unstable. This fix adds a 7-day cooldown to the `.github/dependabot.yml` file, ensuring newly published package versions are vetted before being proposed for update. This is critical for Node.js libraries where vulnerabilities affect all downstream consumers.