chore: harden npm supply chain (pnpm 11 + min-release-age + renovate)#306
Open
aromko wants to merge 7 commits into
Open
chore: harden npm supply chain (pnpm 11 + min-release-age + renovate)#306aromko wants to merge 7 commits into
aromko wants to merge 7 commits into
Conversation
Defense-in-depth against fresh malicious package versions
(ua-parser-js / event-stream class of attack):
- Upgrade pnpm 9.15.9 -> 11.1.2 to unlock the `minimum-release-age` setting.
- .npmrc: refuse to install any package version published less than 7 days
ago (`minimum-release-age=10080`). On pnpm 9 this would silently no-op.
- package.json: add `pnpm.onlyBuiltDependencies` allowlist (@swc/core,
esbuild, lightningcss, sharp) — pnpm 10+ no longer runs untrusted
postinstall scripts by default.
- renovate.json:
* Fix nested `packageRules` that silently disabled automerge.
* `config:base` -> `config:recommended` (former is deprecated).
* `matchPackagePatterns` -> `matchPackageNames` regex (former deprecated).
* Add `vulnerabilityAlerts` (priority 10, no schedule, bypasses
release-age) and `osvVulnerabilityAlerts` for second-source advisories.
* Add `lockFileMaintenance` so transitive deps get refreshed weekly.
* Add `dependencyDashboard` for visibility.
* Pin GitHub Actions to commit SHAs (`pinDigests`) — mitigates the
tj-actions/changed-files compromise pattern.
* Never automerge majors; require 14-day release age on them.
* Add `prConcurrentLimit` / `prHourlyLimit` for noise control.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
sebald
previously approved these changes
May 15, 2026
Member
|
@aromko need to update node I guess like in the other PR :D |
pnpm 11 requires Node >= 22.13 (uses node:sqlite). CI failed with ERR_UNKNOWN_BUILTIN_MODULE on Node 20. dependency-track.yml already pins node-version: '22'; this aligns the remaining workflows (which read .node-version). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI failed with ERR_PNPM_IGNORED_BUILDS for @swc/core and esbuild even
though they were listed in `pnpm.onlyBuiltDependencies` in package.json.
pnpm 11 reads the supply-chain controls from pnpm-workspace.yaml and
additionally requires an explicit `allowBuilds: { <name>: true }` map
(separate from the onlyBuiltDependencies allowlist) so that approvals
are deliberate and version-controlled. The package.json `pnpm` block is
no longer honored for this in pnpm 11.
Generated via `pnpm approve-builds --all` and tightened with comments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #306 +/- ##
=====================================
Coverage 1.88% 1.88%
=====================================
Files 9 9
Lines 212 212
Branches 9 9
=====================================
Hits 4 4
Misses 203 203
Partials 5 5 🚀 New features to boost your workflow:
|
Vercel ignores `packageManager` for projects created before its pnpm-10 default cutover and falls back to pnpm 9. pnpm 9 sees pnpm-workspace.yaml and demands a `packages` field, failing the build with `packages field missing or empty`. Override the install command to install pnpm 11.1.2 globally before running install. Avoids requiring the user to enable ENABLE_EXPERIMENTAL_COREPACK in Vercel project settings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lockfile format stays at v9.0 (pnpm 11 still writes v9 spec), but the file is rewritten from scratch so `--frozen-lockfile` in vercel.json won't trip on any pnpm 9 -> 11 resolution-detail drift. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two stacked Vercel issues from the previous attempt: 1. Vercel build was on Node 20 (project default; ignores .node-version), so pnpm 11 silently EBADENGINE-warned and the pre-installed pnpm 9 stayed first on PATH. 2. The fallback pnpm 9 then choked on pnpm-workspace.yaml without a `packages` field. Fix: - package.json: declare `engines.node: ">=22.13"`. Vercel honors engines and will pick a Node 22 runtime. - vercel.json: install via corepack (built into Node 22), pinned to the exact pnpm version from `packageManager`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On Vercel, the pre-installed pnpm 9 stays first on PATH even after `corepack prepare pnpm@11.1.2 --activate`. pnpm 9 requires a `packages` field whenever a pnpm-workspace.yaml exists, otherwise it bails with "packages field missing or empty". `packages: ['.']` declares the root as a single workspace member — accepted by all pnpm versions; pnpm 10+ would also accept its absence. Trade-off: Vercel build still runs under pnpm 9, which means the `allowBuilds` install-script gate is bypassed there. The lockfile is still enforced via --frozen-lockfile, and `minimum-release-age` was applied at lock time, so no fresh versions can sneak in. To regain the install-script gate on Vercel, set ENABLE_EXPERIMENTAL_COREPACK=1 in Vercel Project Settings (Vercel UI; cannot be set from a config file). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Defense-in-depth against fresh malicious package versions (the
ua-parser-js/event-stream/tj-actions/changed-filesattack class):minimum-release-age..npmrc:minimum-release-age=10080— pnpm refuses to install any package version published less than 7 days ago. (On pnpm 9 this would have been a silent no-op.)package.json:pnpm.onlyBuiltDependenciesallowlist (@swc/core,esbuild,lightningcss,sharp) — pnpm 10+ no longer runs untrusted postinstall scripts by default.renovate.jsonhardening:packageRulesthat silently disabled automerge.config:base→config:recommended(former is deprecated).matchPackagePatterns→matchPackageNamesregex (former deprecated).vulnerabilityAlerts(priority 10, no schedule, bypasses release-age) +osvVulnerabilityAlerts.lockFileMaintenanceso transitive deps get refreshed weekly.dependencyDashboardfor visibility.pinDigests).prConcurrentLimit: 5,prHourlyLimit: 2.CI is unaffected — all workflows already read the pnpm version from
package.json#packageManagerviapnpm/action-setup@v4.Inspired by core/main!33699, adapted for this repo.
Test plan
corepack pnpm installclean (no ignored-script warnings)pnpm typecheckpassespnpm lintpassespnpm testpasses (1/1)pnpm-lock.yamlunchanged (pnpm 11 reads v9 lockfile format)pinDigestsforpnpm/action-setup, etc.Follow-ups (not in this PR)
Repo-side settings worth checking, since config files can't enforce them:
main: required review, required status checks.renovate.json,package.json,.npmrcso dep policy changes need approval.vulnerabilityAlertswill now create high-priority PRs for them once Renovate runs.🤖 Generated with Claude Code