Back to Blog
high SEVERITY7 min read

How Supply Chain Risk from Missing Package Age Validation Happens in pnpm and How to Fix It

A pnpm workspace configuration was missing the `minimumReleaseAge` setting, creating a supply chain vulnerability where newly published (and potentially malicious) packages could be installed immediately. By adding a 10,080-minute (7-day) minimum release age to `pnpm-workspace.yaml`, the project now enforces a critical delay that allows the security community time to identify and report malicious or unstable packages before they reach production environments.

O
By Orbis AppSec
Published August 15, 2026Reviewed August 15, 2026

Answer Summary

The vulnerability is a missing supply chain security control in pnpm's workspace configuration (CWE-345: Insufficient Verification of Data Authenticity). Without the `minimumReleaseAge` setting, newly published npm packages bypass a crucial 7-day grace period that allows the security community to identify malicious code. The fix adds `minimumReleaseAge: 10080` to `pnpm-workspace.yaml`, enforcing a mandatory delay before any newly released package versions can be installed.

Vulnerability at a Glance

cweCWE-345 (Insufficient Verification of Data Authenticity)
fixAdd `minimumReleaseAge: 10080` (7 days in minutes) to pnpm-workspace.yaml
riskMalicious or unstable packages can be installed immediately after publication
languageYAML / Node.js Package Management
root causepnpm-workspace.yaml lacks minimumReleaseAge configuration setting
vulnerabilityMissing Package Release Age Validation in pnpm

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:

  1. An attacker compromises a popular npm package (or creates a typosquatting package with a similar name)
  2. They publish a malicious version to npm at 2:00 PM UTC
  3. Your CI/CD pipeline runs a fresh install at 2:05 PM UTC
  4. 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
  5. 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 audit and 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 minimumReleaseAge is 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 minimumReleaseAge alongside 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...

Frequently Asked Questions

What is minimumReleaseAge in pnpm?

It's a security setting that prevents pnpm from installing package versions published fewer than N minutes ago, giving the security community time to identify and report malicious packages.

How do you prevent supply chain attacks through newly published packages?

Configure `minimumReleaseAge: 10080` in your pnpm-workspace.yaml to enforce a mandatory 7-day waiting period before installing newly released versions.

What CWE applies to missing package age validation?

CWE-345 (Insufficient Verification of Data Authenticity) — the system fails to verify the trustworthiness of newly published package versions.

Is using a lockfile enough to prevent this vulnerability?

No. Lockfiles protect against version changes in existing dependencies, but don't prevent initial installation of malicious new versions if your configuration allows it.

Can static analysis detect missing minimumReleaseAge?

Yes. Semgrep's `package_managers.pnpm.pnpm-missing-minimum-release-age.pnpm-minimum-release-age` rule specifically detects this configuration gap.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #16

Related Articles

critical

How Supply Chain Timing Attacks happen in pnpm Workspaces and how to fix it

The apple-mail-mcp repository was vulnerable to supply chain timing attacks because its pnpm workspace configuration only enforced a 1-day (1440 minute) minimum release age for newly published packages. This allowed a 5-day-old transitive dependency (ip-address@10.5.0) to be installed despite Dependabot's 7-day cooldown, creating a window where malicious or unstable packages could enter the dependency tree. The fix raises minimumReleaseAge to 10080 minutes (7 days) to ensure all packages—includi

high

How run-shell-injection happens in GitHub Actions and how to fix it

A high-severity shell injection vulnerability was discovered in `action.yml` at line 68, where GitHub Actions `${{ inputs.* }}` expressions were directly interpolated into `run:` shell scripts. An attacker who controls input values (like a URL or app name) could inject arbitrary shell commands into the CI runner, potentially stealing secrets and source code. The fix replaces all direct interpolations with intermediate environment variables, properly quoted to prevent injection.

medium

How GitHub Actions Mutable Action Tags Enable Supply-Chain Attacks and How to Fix Them

A GitHub Actions workflow was using `actions/checkout@v1`, a mutable tag reference that could be silently repointed by the action owner to inject malicious code. This supply-chain vulnerability was fixed by pinning the action to a specific commit SHA (`11bd71901bbe5b1630ceea73d27597364c9af683`), ensuring the workflow always executes verified, immutable code.

high

How package_managers.pnpm.pnpm-missing-minimum-release-age.pnpm-minimum-release-age happens in pnpm and how to fix it

A pnpm workspace configuration in `site-astro/pnpm-workspace.yaml` was missing critical supply chain security settings including `minimumReleaseAge`, `trustPolicy`, and `blockExoticSubdeps`. Without these protections, the project could install freshly published malicious packages within minutes of their release. The fix adds a 7-day quarantine period, downgrade protection, and exotic subdependency blocking.

high

How Path Traversal and Security Policy Bypass Happens in Node.js Dependencies and How to Fix It

A high-severity vulnerability in the fast-uri package (CVE-2026-6321) allowed attackers to bypass security policies through improper Unicode hostname canonicalization and path traversal. This issue affected the @apralabs/apra-fleet project through its dependency tree, and was resolved by upgrading fast-uri from version 3.1.0 to 4.1.2 using npm overrides.

high

How Command Injection happens in Node.js child_process calls and how to fix it

A high-severity command injection vulnerability was discovered in `src/collectors/git.ts`, where `execSync` was used to build a shell command by interpolating unsanitized arguments into a template string. By replacing `execSync` with `spawnSync`, the fix eliminates shell interpretation entirely, ensuring that git arguments are passed directly to the process without ever touching a shell. This change is especially important for a Node.js library, where downstream consumers may pass user-controlle