Introduction
In a Node.js library's repository, Semgrep flagged a high-severity supply chain vulnerability in the pnpm-workspace.yaml configuration file at line 1. The workspace configuration was missing the minimumReleaseAge setting—a critical defense mechanism introduced in pnpm v10.16.0. This gap meant the project would immediately install newly-published package versions without any waiting period, exposing downstream consumers to potential supply chain attacks.
The vulnerability is particularly concerning for this Node.js library because any security weakness doesn't just affect the library itself—it impacts every downstream consumer who depends on this package. A compromised dependency could propagate through the entire supply chain.
The Vulnerability Explained
Let's examine the original pnpm-workspace.yaml configuration:
catalog:
ziko: ^1.10.0
vite: ^8.2.1
minimumReleaseAgeExclude:
- ziko@1.10.0
Notice what's missing: there's a minimumReleaseAgeExclude array (line 9) but no corresponding minimumReleaseAge setting. This configuration is dangerous because:
- Immediate Installation: When pnpm resolves dependencies, it will install the newest available version that satisfies the semver range immediately upon publication
- No Vetting Period: There's no grace period for the security community to identify and report malicious packages
- Transitive Risk: The vulnerability extends to all transitive dependencies, not just direct ones
How Could This Be Exploited?
Consider a realistic attack scenario against this specific workspace:
- Package Takeover: An attacker compromises the npm account of a maintainer for a package used by
zikoorvite(transitive dependencies) - Malicious Publication: The attacker publishes a new minor version (e.g., 1.10.1) containing malicious code designed to exfiltrate environment variables or inject backdoors
- Immediate Installation: Within minutes of publication, the next time someone runs
pnpm installin this workspace, the malicious version gets installed - Supply Chain Compromise: The malicious code executes during installation scripts or when the library is imported, potentially compromising CI/CD pipelines, developer machines, or production environments
Real-world examples of this attack pattern include:
- The event-stream incident (2018): A popular npm package was compromised to steal cryptocurrency wallet credentials
- The ua-parser-js attack (2021): Attackers published malicious versions that installed cryptocurrency miners
- The coa and rc attacks (2021): Compromised packages contained password-stealing malware
Without minimumReleaseAge, this workspace has zero protection against these time-sensitive attacks.
The Fix
The security patch adds three layers of defense to pnpm-workspace.yaml:
catalog:
ziko: ^1.10.0
vite: ^8.2.1
# Wait at least 7 days before installing newly published package versions.
minimumReleaseAge: 10080
minimumReleaseAgeExclude:
- ziko@1.10.0
# Prevent transitive dependencies from being installed from untrusted sources.
blockExoticSubdeps: true
# Prevent malicious package updates from downgrading security settings.
trustPolicy: no-downgrade
Breaking Down the Changes
1. Primary Defense - minimumReleaseAge: 10080 (line 9)
This setting enforces a 7-day (10,080 minute) waiting period before pnpm will install newly-published package versions. When a package maintainer publishes version 1.10.1 today, pnpm won't install it until 7 days have passed. This window allows:
- Security researchers to analyze new releases
- The npm security team to identify and remove malicious packages
- The community to report suspicious behavior
- Automated security scanners to flag anomalies
The 7-day period is based on industry research showing most malicious packages are identified and removed within 3-5 days of publication.
2. Transitive Dependency Protection - blockExoticSubdeps: true (line 15)
This setting prevents transitive dependencies from being installed from non-standard sources (git URLs, tarball URLs, local file paths). It ensures all subdependencies come through the npm registry where they're subject to security scanning. Without this, an attacker could compromise a direct dependency to pull in malicious code from an external source, bypassing npm's security controls.
3. Configuration Integrity - trustPolicy: no-downgrade (line 18)
This prevents package updates from weakening security settings. If a compromised package tries to modify .npmrc or pnpm-workspace.yaml to disable minimumReleaseAge or other protections, pnpm will reject the change. This is critical because sophisticated supply chain attacks often try to disable security controls as their first step.
Why Each Change Matters
The fix creates a defense-in-depth strategy:
- minimumReleaseAge provides time-based protection
- blockExoticSubdeps provides source-based protection
- trustPolicy provides configuration-based protection
Together, they address multiple attack vectors that could compromise the supply chain.
Prevention & Best Practices
To protect your pnpm workspaces from supply chain attacks:
1. Always Configure minimumReleaseAge
Add this to every pnpm-workspace.yaml:
minimumReleaseAge: 10080 # 7 days in minutes
For production environments, consider even longer periods (14-30 days) if your update cadence allows.
2. Use Explicit Exclusions Sparingly
The minimumReleaseAgeExclude array should only contain packages where you need immediate updates:
minimumReleaseAgeExclude:
- ziko@1.10.0 # Specific version for critical bug fix
Never exclude entire packages with wildcards—this defeats the protection.
3. Enable All Supply Chain Hardening Features
# Complete hardening configuration
minimumReleaseAge: 10080
blockExoticSubdeps: true
trustPolicy: no-downgrade
verifyStoreIntegrity: true
4. Implement Additional Controls
- Lockfile Integrity: Always commit
pnpm-lock.yamland review changes carefully - Dependency Auditing: Run
pnpm auditregularly and fix vulnerabilities promptly - Update Policies: Establish a process for reviewing dependency updates before merging
- Supply Chain Scanning: Use tools like Socket, Snyk, or GitHub Dependency Review
5. Monitor Security Advisories
Subscribe to:
- npm security advisories
- GitHub Security Advisories for your dependencies
- Security mailing lists for critical packages
Security Standards
This vulnerability and fix align with:
- OWASP Top 10 2021 - A06:2021 – Vulnerable and Outdated Components
- CWE-1357: Reliance on Insufficiently Trustworthy Component
- SLSA (Supply Chain Levels for Software Artifacts) framework recommendations
- NIST SP 800-161r1 - Cybersecurity Supply Chain Risk Management
Key Takeaways
- The
pnpm-workspace.yamlfile lackedminimumReleaseAge, allowing immediate installation of potentially malicious newly-published packages without any vetting period - A 7-day waiting period (10,080 minutes) provides critical time for the security community to identify and report compromised packages before they reach your project
- The presence of
minimumReleaseAgeExcludewithoutminimumReleaseAgecreated a false sense of security—the exclusion list had no base policy to exclude from - Supply chain attacks target Node.js libraries specifically because compromising one library can affect thousands of downstream consumers through transitive dependencies
- Three-layer defense (minimumReleaseAge + blockExoticSubdeps + trustPolicy) provides comprehensive protection against multiple supply chain attack vectors
How Orbis AppSec Detected This
- Source: pnpm package resolution system pulling packages directly from npm registry
- Sink: Package installation in
pnpm-workspace.yamlwithout any time-based verification controls - Missing control: No
minimumReleaseAgeconfiguration to delay installation of newly-published package versions - CWE: CWE-1357 (Reliance on Insufficiently Trustworthy Component)
- Fix: Added
minimumReleaseAge: 10080to enforce a 7-day waiting period, plusblockExoticSubdepsandtrustPolicyfor additional supply chain hardening
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
The missing minimumReleaseAge configuration in this pnpm workspace represented a critical gap in supply chain security defenses. By adding a 7-day waiting period along with additional hardening controls, the project now has robust protection against malicious or compromised packages. This fix is particularly important for Node.js libraries where vulnerabilities propagate to all downstream consumers.
Supply chain security requires defense in depth—no single control is sufficient. The combination of time-based delays, source restrictions, and configuration integrity checks creates multiple barriers that attackers must overcome. Every Node.js project using pnpm should implement these protections to defend against increasingly sophisticated supply chain attacks.
Remember: in supply chain security, time is your ally. A few days of delay in adopting new packages is a small price to pay for the security of your entire dependency tree.
References
- CWE-1357: Reliance on Insufficiently Trustworthy Component
- pnpm minimumReleaseAge Documentation
- OWASP Software Component Verification Standard
- Semgrep Rule: pnpm-missing-minimum-release-age
- GitHub PR: harden: this pnpm workspace configuration does not set ... in...
- SLSA Supply Chain Security Framework