Introduction
In the site-astro project, we discovered a high severity supply chain security misconfiguration in pnpm-workspace.yaml. The workspace configuration file — responsible for governing how pnpm resolves and installs dependencies for an Astro-based website — was missing three critical security hardening settings. Most notably, the absence of minimumReleaseAge meant that any freshly published npm package version could be pulled into the project immediately, before the community had any chance to identify if it was compromised.
This matters because supply chain attacks on npm are not theoretical. The event-stream, ua-parser-js, and colors incidents demonstrated that attackers routinely publish malicious versions of popular packages. Without a quarantine period, automated dependency updates (or even manual pnpm update commands) could pull in a compromised package within minutes of its publication.
The Vulnerability Explained
What Was Missing
The original site-astro/pnpm-workspace.yaml contained only a basic configuration:
onlyBuiltDependencies:
- esbuild
- sharp
catalog:
astro: ^5.16.0
This configuration tells pnpm which packages are allowed to run build scripts (esbuild and sharp) and defines a version catalog for Astro. However, it's missing three security-critical settings that pnpm v10.16.0+ supports:
minimumReleaseAge— No quarantine period for newly published packagestrustPolicy— No protection against security setting downgradesblockExoticSubdeps— No blocking of unusual transitive dependencies
How This Could Be Exploited
Consider this attack scenario specific to this project:
- An attacker identifies that
site-astrodepends onastro: ^5.16.0(visible in the catalog) - The attacker compromises the npm credentials of a maintainer of any package in Astro's dependency tree
- They publish a malicious patch version (e.g., bumping a transitive dependency from
1.2.3to1.2.4) - A developer on the
site-astroproject runspnpm update— the malicious version is installed immediately - The malicious code executes during the build process (since
esbuildandsharpalready have build script permissions)
Without minimumReleaseAge, there's zero delay between publication and potential installation. Most supply chain attacks are detected within hours to days — a 7-day quarantine would catch the vast majority.
The Compounding Risk
The missing trustPolicy: no-downgrade setting compounds this risk. An attacker who gains partial control could potentially downgrade security settings in the lockfile, removing protections that were previously in place. The missing blockExoticSubdeps: true means transitive dependencies could introduce unusual package sources that bypass normal npm registry vetting.
The Fix
The fix adds three lines to site-astro/pnpm-workspace.yaml, inserting them between the onlyBuiltDependencies list and the catalog section:
Before
onlyBuiltDependencies:
- esbuild
- sharp
catalog:
astro: ^5.16.0
After
onlyBuiltDependencies:
- esbuild
- sharp
trustPolicy: no-downgrade
blockExoticSubdeps: true
minimumReleaseAge: 10080
catalog:
astro: ^5.16.0
What Each Setting Does
minimumReleaseAge: 10080 — The value 10080 is in minutes, which equals exactly 7 days. pnpm will refuse to install any package version that was published less than 7 days ago. This gives the security community time to detect and report compromised packages before they reach your project.
trustPolicy: no-downgrade — Prevents the lockfile from having its security settings downgraded. If a malicious actor modifies the lockfile (e.g., via a compromised CI pipeline or a deceptive PR), pnpm will reject changes that weaken security posture. This was added in pnpm v10.21.0.
blockExoticSubdeps: true — Blocks transitive dependencies that come from unusual sources (git repositories, tarballs, etc.) rather than the standard npm registry. This prevents attackers from sneaking in unvetted code through deep dependency chains.
Why This Is Behavior-Preserving
These settings only affect the timing and source of package installations, not functionality. Any package that has been published for more than 7 days will install normally. The project's existing dependencies (already in the lockfile) are unaffected because they were published long ago. Only new updates are subject to the quarantine.
Prevention & Best Practices
1. Always Configure Supply Chain Security Settings
For any project using pnpm v10.16.0+, include these settings in your pnpm-workspace.yaml:
minimumReleaseAge: 10080 # 7-day quarantine (minutes)
trustPolicy: no-downgrade # Prevent security downgrades
blockExoticSubdeps: true # Block non-registry transitive deps
2. Use Static Analysis on Configuration Files
Security scanners like Semgrep can detect missing security settings in package manager configurations. Include rules like package_managers.pnpm.pnpm-missing-minimum-release-age in your CI pipeline.
3. Layer Your Defenses
Supply chain security requires defense-in-depth:
- Lockfiles prevent unexpected changes during pnpm install
- minimumReleaseAge protects during intentional updates
- onlyBuiltDependencies limits which packages can run scripts
- trustPolicy prevents security regression
- Code review catches suspicious dependency changes
4. Monitor for Supply Chain Advisories
Subscribe to npm security advisories and use tools like pnpm audit regularly. The 7-day quarantine gives time for advisories to be published before you're affected.
5. Consider Stricter Values for High-Security Projects
For critical infrastructure, consider minimumReleaseAge: 20160 (14 days) or even longer. The tradeoff is slower access to new features vs. stronger protection against zero-day supply chain attacks.
Key Takeaways
- The
site-astro/pnpm-workspace.yamlfile had zero supply chain quarantine protection — any freshly published malicious package could be installed immediately during updates minimumReleaseAge: 10080provides a 7-day safety net that catches the majority of supply chain attacks, which are typically detected within hours to daystrustPolicy: no-downgradeprevents a subtle attack vector where security settings in the lockfile are weakened through seemingly innocent PRs or CI modifications- Supply chain hardening in pnpm is a 3-line change that provides significant protection with zero impact on existing functionality
- Configuration-level security settings are often overlooked — the
onlyBuiltDependencieslist showed security awareness, but the newer pnpm hardening features hadn't been adopted yet
How Orbis AppSec Detected This
- Source: npm registry — newly published package versions available for installation without age verification
- Sink:
pnpm-workspace.yamlat the root configuration level insite-astro/, where dependency resolution policies are defined - Missing control: No
minimumReleaseAgesetting to enforce a quarantine period, notrustPolicyto prevent security downgrades, and noblockExoticSubdepsto restrict transitive dependency sources - CWE: CWE-829 (Inclusion of Functionality from Untrusted Control Sphere)
- Fix: Added
minimumReleaseAge: 10080,trustPolicy: no-downgrade, andblockExoticSubdeps: truetosite-astro/pnpm-workspace.yaml
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 remain one of the most dangerous threats to modern software projects. The site-astro project's pnpm-workspace.yaml was missing critical hardening settings that pnpm provides specifically to combat these attacks. By adding minimumReleaseAge: 10080, trustPolicy: no-downgrade, and blockExoticSubdeps: true, the project now has a 7-day quarantine for new packages, protection against security setting downgrades, and blocking of exotic transitive dependencies.
If you're using pnpm v10.16.0 or later, audit your pnpm-workspace.yaml files today. These three lines of configuration provide meaningful protection against an entire class of supply chain attacks — at zero cost to your development workflow.