Skip to content
Fran Gonzalez
← Back to blog
(updated Jun 5, 2026) · Clanker · 5 min read

Keeping Supply Chain Exclusions Honest

Your pnpm security config decays over time. minimumReleaseAgeExclude entries pile up, trustPolicyExclude entries become stale, and allowBuilds lists drift from reality. Here's how to catch it.

The first post in this series covered setting up pnpm’s supply chain controls. The second covered automated updates with cooldowns. This post covers the part I kept postponing: keeping the config from rotting.

The Problem

When I first set up minimumReleaseAgeExclude, trustPolicyExclude, and allowBuilds, each entry had a clear reason. But dependency trees change. Packages get upgraded, new ones get added, old ones get removed. The exclusion lists don’t clean themselves up — they only grow.

I found this while applying the same security setup to a second project. The first project had 31 overrides that weren’t doing anything. The second had minimumReleaseAgeExclude entries for packages published months ago, well past the age window. The configs looked hardened but were full of dead weight.

The Three Lists That Decay

minimumReleaseAgeExclude

This list exempts packages from the minimumReleaseAge check. It grows in two ways:

  1. Manual additions — I need a fresh release and add an entry to unblock it
  2. Automatic additionspnpm audit --fix=update adds entries when patching vulnerabilities, so the patched version can install without waiting for the age window

The problem: entries are never removed. There’s no built-in cleanup mechanism (pnpm#11668). A minimumReleaseAgeExclude entry for a package published months ago is doing nothing — the package is already past the age window, so the exclusion is pure noise.

There’s also a bug where pnpm audit --fix update adds entries even for packages that wouldn’t be blocked (pnpm#11563). The list grows faster than it should.

trustPolicyExclude

This list exempts packages from the trustPolicy: no-downgrade check. It’s needed when a package doesn’t ship with provenance attestations but is known-safe.

The entries age out as upstream packages adopt provenance. A trustPolicyExclude for chokidar@4.0.3 was justified six months ago — the pinned version lacked provenance. But the latest release now ships with provenance, so the exclusion is holding back a security control for no reason.

allowBuilds

This list whitelists packages that may run install scripts. It should match the packages in your dependency tree that actually have postinstall scripts. But dependency trees change — packages get removed, new ones get added, and the allowlist drifts.

An allowBuilds entry for a package that’s no longer installed is harmless but confusing. An entry that’s missing for a newly added package causes pnpm install to fail, which is the correct behavior with strictDepBuilds: true.

The Audit Workflow

There’s no automated tool that cleans up these lists. The practical approach is a manual review, which takes minutes when done regularly.

Step 1: Check what’s installed

For allowBuilds, I verify each entry against the actual dependency tree:

pnpm ls @parcel/watcher
pnpm ls core-js
pnpm ls esbuild

If pnpm ls returns nothing, the package isn’t installed and doesn’t need an allowBuilds entry.

Step 2: Check publish dates

For minimumReleaseAgeExclude, I check whether entries are still needed:

pnpm info astro@6.3.8 --json | grep -A2 '"time"'

If the package was published well past the minimumReleaseAge window (months ago), the exclude is doing nothing. Remove it.

Step 3: Check provenance

For trustPolicyExclude, I check whether the excluded package now ships with provenance:

pnpm info chokidar@4.0.3 --json | grep -A5 '"attestations"'

If provenance has a URL, the package now has attestations and the exclude can be removed (after upgrading to the version that has provenance).

Step 4: Run pnpm audit

pnpm audit --prod

This catches known vulnerabilities regardless of exclusion lists. If audit finds issues, the exclusions aren’t protecting from everything.

When to Schedule Reviews

The review doesn’t need to be frequent. Good triggers:

  • When upgrading packages — exclusions for old versions may no longer apply
  • When pnpm audit finds new advisories — check whether exclusions are blocking fixes
  • When adding new dependencies — verify allowBuilds covers any new install scripts
  • Quarterly — a standing calendar reminder to check the lists even if nothing else changed

Partial Automation

Renovate’s customManagers can detect version strings in pnpm-workspace.yaml and create PRs to update them. This keeps exclusion versions current but can’t decide whether an entry should be deleted. It’s a useful supplement, not a replacement for manual review.

The pnpm team is considering a pnpm cleanup command that would auto-prune stale entries (pnpm#11668). Until that lands, the workflow is manual.

What I’d Do Differently

I’d run this review quarterly from the start instead of discovering the staleness when applying the config to a second project. The exclusion lists were doing real work when I added them — I just never went back to check whether they still were.

References