Introduction
The pnpm-workspace.yaml file is the control center for how pnpm resolves, builds, and trusts every dependency in a Node.js monorepo. In this repository, that file defined the workspace's packages and an allowBuilds list for native modules like @discordjs/opus and esbuild, but it never set a trustPolicy. That's a small omission with an outsized consequence: without an explicit trust policy, pnpm falls back to more permissive behavior when a dependency publishes a new release, which means the trust evidence pnpm has already recorded for a package could quietly be downgraded by a future update.
This matters for any team relying on pnpm-workspace.yaml to manage third-party code, because the workspace config is exactly the kind of file that rarely gets a second look after initial setup — until an automated scanner (in this case, Semgrep) flags it.
The Vulnerability Explained
Before the fix, pnpm-workspace.yaml looked like this:
packages:
- "."
allowBuilds:
'@discordjs/opus': true
esbuild: true
There is no trustPolicy key anywhere in the file. Since pnpm 10.21.0, this setting exists specifically to answer one question: if a package publishes a new version, is pnpm allowed to accept trust evidence that is weaker than what it already recorded? Without an explicit no-downgrade policy, the answer defaults to "yes" — pnpm will accept the new release's trust metadata even if it represents a regression.
Concretely, imagine a legitimate maintainer's npm account for a transitive dependency is compromised, or a malicious actor publishes a typosquat-adjacent update that manipulates provenance/trust signals. If the workspace has no trustPolicy: no-downgrade, pnpm has no built-in rule stopping that update from silently lowering the bar the next time pnpm install or pnpm update runs in this repository. The attacker doesn't need to exploit application code directly — they just need to get a downgraded-trust package accepted during a routine dependency bump, at which point it becomes a foothold for further supply-chain compromise (e.g., paired with a malicious postinstall script or a build step enabled via allowBuilds).
In a real-world scenario for this specific repo: the allowBuilds section already grants build permissions to @discordjs/opus and esbuild. If either of those packages' publisher trust were downgraded by a future malicious release, and no trustPolicy guard existed, pnpm would have no additional line of defense — the combination of "trust downgrade allowed" plus "build execution allowed" is exactly the kind of chainable primitive automated exploit tooling looks for.
The Fix
The fix is minimal but precise — a single new top-level key added to pnpm-workspace.yaml:
Before:
packages:
- "."
allowBuilds:
'@discordjs/opus': true
esbuild: true
After:
packages:
- "."
trustPolicy: no-downgrade
allowBuilds:
'@discordjs/opus': true
esbuild: true
By setting trustPolicy: no-downgrade, pnpm now enforces that any dependency update accepted into this workspace cannot regress the publisher trust evidence pnpm previously established for that package. If a future release attempts to weaken that trust signal, pnpm rejects it rather than silently installing it.
The accompanying CHANGELOG.md update makes the intent explicit for downstream consumers:
- Reject dependency releases with downgraded publisher trust evidence while preserving the 48-hour release-age policy. (#8) Thanks @anupamme.
This one-line config change requires no code changes elsewhere in the project because it operates entirely at the package-manager level — it doesn't affect how existing valid packages install or build, it only adds a rejection path for a specific class of malicious update.
Prevention & Best Practices
- Always set
trustPolicyexplicitly inpnpm-workspace.yamlrather than relying on defaults. Useno-downgradeunless you have a specific, documented reason not to. - Combine trust policy with
minimumReleaseAge(referenced in this repo's changelog as the "48-hour release-age policy") to add a time buffer before newly published versions are trusted — this gives the community time to catch and report malicious releases before your CI ever pulls them. - Audit
allowBuildsregularly. Packages granted build permissions (like@discordjs/opusandesbuildhere) can execute arbitrary code during install; pair build allowlists with strict trust enforcement. - Run Semgrep or equivalent supply-chain rules in CI so configuration regressions (like a missing
trustPolicy) are caught automatically before merge, not discovered after an incident. - Keep pnpm current.
trustPolicywas only introduced in pnpm 10.21.0 — teams on older versions need to upgrade pnpm itself before this control is even available. - Reference OWASP's guidance on Software Supply Chain Security for broader dependency risk management practices.
Key Takeaways
pnpm-workspace.yamlhad zerotrustPolicyconfiguration, defaulting the workspace to permissive trust handling on every dependency update.- The fix adds exactly one line —
trustPolicy: no-downgrade— with no application code changes required. - This workspace also grants build execution via
allowBuildsfor@discordjs/opusandesbuild, which raises the stakes of any trust-downgrade path being left open. - Trust policy enforcement pairs with release-age policies (noted in the changelog) as complementary, not redundant, supply-chain defenses.
- This is a config-level control, not an application-level one — it's enforced by pnpm itself on every
install/update, making it a low-cost, high-leverage fix.
How Orbis AppSec Detected This
- Source: Dependency update events processed by pnpm during
install/updateoperations againstpnpm-workspace.yaml. - Sink: pnpm's dependency trust-resolution logic, which reads workspace configuration to decide whether to accept a package's trust evidence.
- Missing control: No
trustPolicykey was defined, so pnpm had no explicit instruction to reject trust-evidence downgrades on package updates. - CWE: CWE-1357 — Reliance on Insufficiently Trustworthy Component.
- Fix: Added
trustPolicy: no-downgradetopnpm-workspace.yaml, instructing pnpm to reject any dependency release that downgrades previously established publisher trust evidence.
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
A missing trustPolicy in pnpm-workspace.yaml is easy to overlook because it's a configuration gap, not a broken function or an injected string. But in a supply-chain context, configuration is the attack surface. This project's fix — adding trustPolicy: no-downgrade alongside its existing allowBuilds permissions — closes off a path where a future malicious or compromised package release could quietly weaken the trust guarantees pnpm had already established, without touching a single line of application logic. Treat your package manager's workspace config with the same scrutiny as your source code: a one-line omission here can be the difference between blocking a supply-chain attack and enabling one.